【问题标题】:How to sync N processes to wait for each other through semaphore如何通过信号量同步N个进程互相等待
【发布时间】:2017-12-05 22:15:47
【问题描述】:

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;
    }
}

【问题讨论】:

  • ... Linux 已经以pthread_barrier_t 及其关联的pthread_barrier_init()*_destroy()*_wait() 函数的形式实现了屏障。还是需要您自己实现?
  • 您不需要信号量,您需要在共享内存中分配pthread_barrier_t,并将其pshared 属性设置为PTHREAD_PROCESS_SHARED
  • @John Bollinger 我不需要实现任何东西
  • 我该如何实现@EOF
  • @BryanShtjefni 你的两个 cmets 似乎是矛盾的。你能澄清一下吗?

标签: c linux process semaphore


【解决方案1】:

每个进程都需要等到所有其他进程都完成一个任务才能同时移动到第二个任务。

我正在考虑实现一个信号量……

是的,您可以以有效的方式实现它System V semaphore 被初始化为进程数 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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-22
    • 2017-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    相关资源
    最近更新 更多