I have a so-called distributor
program which spawns another program af_xdp_user
for each IP-address passed to distributor
. Before doing this, distributor
generates a shared memory:
int create_shrd_memory(uint64_t size) {
const int shmid = shmget(SHM_KEY, size, IPC_CREAT | IPC_EXCL);
if(shmid == -1) {
if(errno == EEXIST) {
printf("Shared memory with Key %d already exists, continue...\n", SHM_KEY);
return SHM_KEY;
} else {
fprintf(stderr, "Failed to obtain Shared Memory: %s\n", strerror(errno));
perror("shmget");
exit(1);
}
}
return shmid;
}
This shared-memory-key is then passed to each sub-process as a command line argument (along several other arguments):
#define SHM_KEY 0x1235
bool global_exit = false;
static void exit_application(int signal)
{
signal = signal;
global_exit = true;
}
int main(int argc, char **argv) {
const uint8_t amnt_of_ip_addrs = argc - 1;
const int shmid = create_shrd_memory( sizeof(struct stats_record) * amnt_of_ip_addrs );
char shrdmemid[96];
char shrdmemidx[96];
pid_t childs[amnt_of_ip_addrs];
for(uint8_t ip_index = 1; ip_index < argc; ip_index++) {
printf("Forked for IP: %s\n", argv[ip_index]);
pid_t pid = fork();
if(pid == 0) { /* child */
static char argv_child[13][18] = { "af_xdp_user", "--dev", "eth20", "--shrdmem", "", "--shrdmemidx", "", "--progsec", "xdp_sock", "--filename", "af_xdp_kern.o", "-Q", ""};
sprintf(shrdmemid, "%d", shmid);
sprintf(shrdmemidx, "%d", ip_index - 1);
strcpy(argv_child[4], shrdmemid);
strcpy(argv_child[6], shrdmemidx);
strcpy(argv_child[12], shrdmemidx);
printf("Arguments:\n");
for(uint8_t arg_idx = 0; arg_idx < sizeof(argv_child) / sizeof(argv_child[0]); arg_idx++) {
printf("\t%s\n", argv_child[arg_idx]);
}
execl("af_xdp_user", argv_child[0], argv_child[1], argv_child[2], argv_child[3], argv_child[4], argv_child[5], argv_child[6], argv_child[7], argv_child[8], argv_child[9], argv_child[10], NULL);
} else if(pid < 0) {
printf("FORK FAILED!\n");
} else {
// childs[ip_index - 1] = pid;
}
}
signal(SIGINT, exit_application);
while(!global_exit) {
print_statistics(amnt_of_ip_addrs);
sleep(2);
}
}
With print_statistics
being a function that accesses (in the future all stats_record
structs) the first stats_record
-struct of the shared memory and prints the amount of received packets:
void print_statistics(const int amnt_of_processes) {
printf("STATISTICS:\n");
char *shmd = shmat(SHM_KEY, NULL, 0);
struct stats_record *stats = (struct stats_record*)(shmd);
printf("\tREC PACKETS: %lu\n", stats->rx_packets);
}
Each subprocess with the program af_xdp_user
then writes certain statistics about received IP-packets in a struct stats_record
like this:
char *shm_data = shmat(cfg->shrdmem_id, NULL, 0);
if(shm_data == -1) {
fprintf(stderr, "Failed to obain shared memory: %s\n", strerror(errno));
exit(1);
}
struct stats_record *stats = (struct stats_record*)(shm_data + sizeof(struct stats_record) * cfg->shrdmem_idx);
...
stats->rx_bytes += amnt_of_packets * bytes;
stats->rx_packets += rcvd;
shmdt(shm_data);
I don't know if I got the idea of fork()
right but I get this strange output:
$ sudo ./distributor 127.0.0.1
Shared memory with Key 4661 already exists, continue...
Forked for IP: 127.0.0.1
STATISTICS:
Arguments:
af_xdp_user
--dev
eth20
--shrdmem
4661
--shrdmemidx
0
--progsec
xdp_sock
--filename
af_xdp_kern.o
-Q
0
SHRDMEM-ID: 4661
SHRDMEM-IDX: 0
Segmentation fault
$ RX-Queue: 0
...
Failed to obain shared memory: Invalid argument
Notice the second $
I get on the command line. In my opinion, this means that distributor
exited, but I don't know why it would exit?
I did some investigations on your program. Your segmentation fault is caused by this:
char *shmd = shmat(SHM_KEY, NULL, 0);
The shmat
function must be used whith the generated ID and NOT the IPC key SHM_KEY
.
Let's remember that the diagram is as follows :
1- Call shmget with IPC_MEMORY_KEY
to get IPC_MEMORY_ID
2- Call shmat with the generated IPC_MEMORY_ID
In your case char *shmd = shmat(SHM_KEY, NULL, 0);
you call shmat
with a Key
and not an ID
. Therefore, your pointer is not valid.
In addition, i noticed that your program created abandoned shared memories:
ipcs -m
you must delete them in your code by calling :
shmctl(IPC_MEMORY_ID , IPC_RMID ,NULL); // ID and not Key !
Or, by commande line :
ipcrm -m MEM_ID (and not Key)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.