我的目标是尝试找到一种在共享内存上读取和写入多个进程的方法。到目前为止,我已经能够只进行两个流程沟通,而我无法绕过如何进行更多沟通。我做了一个项目,其中N个进程A在共享内存上写入数据,然后N个进程B读取这个共享内存并将自己的数据发送回他们决定与之交谈的进程A.我也必须使用共享内存和信号量。
array:1 [▼
0 => array:3 [▼
"school_id" => "4"
"order_date" => "11/25/2017"
"time_slot" => "10am - 8pm"
]
]
我想将此代码改为多个进程而不是两个进程。如果您有其他选择,请随时发布。
答案 0 :(得分:0)
直到现在,我只能使两个进程进行通信,而无法解决如何进行更多通信的问题。
要将程序扩展到多个子进程对,请使用semaphore sets(每个进程一个信号量)而不是普通信号量。下面是您的程序的稍作修改的变体,可对N对进行此操作。
/* cc -std=c99 -lrt */
#define _SVID_SOURCE
#define _DEFAULT_SOURCE
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdatomic.h>
int main()
{
key_t key;
char *virtualaddr;
int get, put;
int shmid;
#define BUF_SIZE BUFSIZ
char buf[BUF_SIZE];
key = ftok("anyfile", 'R');
#define N 4
atomic_int *a; // where the process counter is at the end of the shared mem
shmid = shmget(key, 1024*N + sizeof*a, 0644|IPC_CREAT); // 1 kiB per process
if (0 > shmid)
{
perror("Shared Mem creation error\n");
exit(1);
}
//Attaching the shared mem to my address space (available across fork)
virtualaddr = shmat(shmid, (void *)0, 0);
a = (void *)&virtualaddr[1024*N];
*a = 0;
//Create two semaphore sets, get and put; Linux initializes the values to 0.
get = semget('g', N, IPC_CREAT|0644);
put = semget('p', N, IPC_CREAT|0644);
for (int n = 0; n < N; ++n)
// N children A
switch (fork())
{
case -1:
printf("Error forking child A!\n");
exit(1);
case 0:
printf("\nChild A%d executing...\n", n);
//Referring the semaphore sets:
get = semget('g', 0, 0);
put = semget('p', 0, 0);
//Child A writing in shared mem
sprintf(virtualaddr+1024*n, "Hello world, I'm child A%d\n", n);
//Child A signalling that now child B can write
semop(get, &(struct sembuf){ n, 1 }, 1);
//Child A waiting for Child B to write..
semop(put, &(struct sembuf){ n, -1 }, 1);
//Child A reading from shared mem
strcpy(buf, virtualaddr+1024*n);
printf("Message received child A%d: %s", n, buf);
printf("Exiting child A%d...\n", n);
_exit(0);
break;
default:
break;
}
for (int n = 0; n < N; ++n)
// N children B
switch (fork())
{
case -1:
printf("Error forking child B!\n");
exit(1);
case 0:
printf("\nChild B%d executing...\n", n);
//Referring the semaphore sets:
get = semget('g', 0, 0);
put = semget('p', 0, 0);
int i = (*a)++; // [somewhat] randomly select one of the A processes
//Waiting till Child A has written
semop(get, &(struct sembuf){ i, -1 }, 1);
//Now child B can read from shared memory
strcpy(buf, virtualaddr+1024*i);
//Child B writing in shared mem
sprintf(virtualaddr+1024*i, "Hello world, I'm child B%d\n", n);
//Signalling that now Child A can read.
semop(put, &(struct sembuf){ i, 1 }, 1);
printf("Exiting child B%d...\n", n);
printf("Message received child B%d: %s", n, buf);
_exit(EXIT_SUCCESS);
break;
default:
break;
}
printf("Parent waiting for children completion...\n");
while (wait(NULL) > 0) ;
if (errno != ECHILD)
{
printf("Error waiting.\n");
exit(EXIT_FAILURE);
}
printf("Parent finishing.\n");
//Deleting semaphore sets:
semctl(get, 0, IPC_RMID);
semctl(put, 0, IPC_RMID);
//Deleting Shared Memory.
shmctl (shmid, IPC_RMID, NULL);
exit(EXIT_SUCCESS);
}