[英]Spawn multiple processes with fork() and pass shared memory key as cmd arg
I have a so-called distributor
program which spawns another program af_xdp_user
for each IP-address passed to distributor
.我有一个所谓的
distributor
程序程序,它为传递给distributor
程序的每个 IP 地址生成另一个程序af_xdp_user
。 Before doing this, distributor
generates a shared memory:在此之前,
distributor
生成一个共享内存:
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: print_statistics
是一个函数,它访问(将来所有stats_record
结构)共享内存的第一个stats_record
-struct 并打印接收到的数据包数量:
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:每个带有程序
af_xdp_user
子af_xdp_user
然后在struct stats_record
写入有关接收到的 IP 数据包的某些统计信息,如下所示:
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:我不知道我对
fork()
的想法是否正确,但我得到了这个奇怪的输出:
$ 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?在我看来,这意味着
distributor
退出了,但我不知道它为什么会退出?
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
. shmat
函数必须与生成的ID一起使用,而不是 IPC密钥SHM_KEY
。
Let's remember that the diagram is as follows :让我们记住图表如下:
1- Call shmget with IPC_MEMORY_KEY
to get IPC_MEMORY_ID
1- 使用
IPC_MEMORY_KEY
调用 shmget 以获取IPC_MEMORY_ID
2- Call shmat with the generated IPC_MEMORY_ID
2- 使用生成的
IPC_MEMORY_ID
调用 shmat
In your case char *shmd = shmat(SHM_KEY, NULL, 0);
在你的情况下
char *shmd = shmat(SHM_KEY, NULL, 0);
you call shmat
with a Key
and not an ID
.您使用
Key
而不是ID
调用shmat
。 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.