如何同步N个进程以通过信号量

时间:2017-12-05 22:15:47

标签: c linux process semaphore

Linux,C。

我必须同步从一个父分叉的N个进程。

每个进程都需要等待所有其他进程完成任务,然后才能同时进入第二个任务。

我正在考虑实施信号量,但我真的不知道哪种类型以及如何以有效的方式实现它。

有人能告诉我这样做的方法吗?

有没有人能解决这个问题?

以下是我想要实现的一些伪代码:

for (int i = 0; i < init_people; ++i) {

    switch (pids[i] = fork()) {
        case -1:
            exit(1);
            break;
        case 0:
            switch (i % 2) {
                case 0:

                    /*Here is where one of the processes starts and 
                    does his task*/ 

                    execve("./A",args,NULL);

                    /*Here is where it stops and waits for all the 
                    other processes to complete the task*/

                    break;

                case 1:

                    /*Here is where one of the processes starts and 
                    does his task*/

                    execve("./B",args,NULL);
                    break;

                    /*Here is where it stops and waits for all the 
                    other processes to complete the task*/

                default:
                    break;
            }
            exit(0);
            break;

        default:
            waitpid(pids[i], &returnStatus, 0);
            break;
    }
}

1 个答案:

答案 0 :(得分:0)

  

每个进程都需要等到所有其他进程都完成一个任务,然后才能全部移至第二个任务。

     

我正在考虑实现信号量

是的,您可以使用System V semaphore 以有效的方式实现,该laravel-model-uuid初始化为进程数N,每个进程在完成第一个任务并等待时都会递减在继续执行第二项任务之前变为零。我完成了(并在建议的地方更改了)您的伪代码。

#define _XOPEN_SOURCE
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main()
{
    #define N   2
    const int init_people = N;
    pid_t pids[N];
    char *task[N] = { "./A 1", "./B 1" };
    char *second_task[N] = { "./A 2", "./B 2" };
    int sem = semget(IPC_PRIVATE, 1, S_IRWXU);  // create a semaphore
    semctl(sem, 0, SETVAL, init_people);        // initialize the value to N
    for (int i = 0; i < init_people; ++i)
        switch (pids[i] = fork())
        {
        case -1:
            exit(1);
        case 0:
            /*Here is where each of the processes starts and
            does his task*/ 
            system(task[i]);    // execve wouldn't return
            /*Here is where it stops and waits for all the 
            other processes to complete the task*/
            // decrement the semaphore value
            semop(sem, &(struct sembuf){.sem_op=-1}, 1);
            // wait until value is zero
            while (semop(sem, &(struct sembuf){}, 1) < 0)
                if (errno != EINTR) perror("semop"), exit(1);
            /*Here all move to the second task simultaneously*/
            system(second_task[i]);
            exit(0);
        }
    do ; while (wait(NULL) > 0);
    if (errno != ECHILD) perror("wait");
    semctl(sem, 0, IPC_RMID);   // remove the semaphore
}