N个进程之间的共享内存c

时间:2017-12-04 11:15:48

标签: c linux process semaphore

我的目标是尝试找到一种在共享内存上读取和写入多个进程的方法。到目前为止,我已经能够只进行两个流程沟通,而我无法绕过如何进行更多沟通。我做了一个项目,其中N个进程A在共享内存上写入数据,然后N个进程B读取这个共享内存并将自己的数据发送回他们决定与之交谈的进程A.我也必须使用共享内存和信号量。

array:1 [▼
  0 => array:3 [▼
    "school_id" => "4"
    "order_date" => "11/25/2017"
    "time_slot" => "10am - 8pm"
  ]
]

我想将此代码改为多个进程而不是两个进程。如果您有其他选择,请随时发布。

1 个答案:

答案 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);
}