等待所有进程到达程序中的某个点,然后恢复

Wait for all processes reach some point in program, then resume

我有一个通过 fork() 创建许多进程的应用程序。在某些时候,我想暂停它们并等待它们全部完成之前的任务。然后一次启动它们。

for (int i = 0; i < N; i++)
{
    if(fork() == 0)
    {
         //some operations here
          <----- wait here for all N forked processes
         //some operations I want all processes start at similiar time

我不希望 children 中的任何一个退出。

与进程通信的方式有很多种,称为IPC(Inter Process Communication)。这取决于您需要发送什么样的信息,有多大等。过程信号也是控制过程的一种方式。

这里有一些资源可以帮助您入门:

  1. 我个人喜欢 Beej Guides,它很棒、清晰、简洁而且免费! http://beej.us/guide/bgipc/
  2. 还有 CodeSourcery LLC 的高级 Linux 编程。 http://www.advancedlinuxprogramming.com/
  3. 当然,一旦您对基础知识有了一些了解,您可以更具体地查找 http://whosebug.com,即在这里:-)

您可以使用像信号量这样的同步结构。 在你想要停止所有孩子的代码点让他们在队列中等待(调用 wait on a semaphore with 0 as initial value )of semaphore 因此他们都会阻塞。

在 parent 然后你可以发出信号量并因此启动它们。

为此,我强烈推荐 Message Passing Interface (MPI),因为它具有 MPI_Barrier,您可以使用它来准确地实现您想要的,几乎不需要您自己编写代码的逻辑。还有其他选择,例如 OpenMP。

我已经通过群组信号解决了这个问题:

for (int i = 0; i < N; i++)
{
    if(fork() == 0)
    {
         /* save first process pid in shared memory */
         if(localID == 0)
             *sh_temp = getpid();

         /* wait in all processes for shared memory with group id to be set  */
         while(*sh_temp == 0)
             usleep(10000);

         /* set group id to first process PID */
         setpgid(getpid(), *sh_temp);

         //some operations here

         fprintf(stderr, "Process %d paused... W8ing for signal to resume\n", getpid());
         raise(SIGSTOP);

         //some operations I want all processes start at similiar time
    }
 }

 if(parentPID == getpid())
 {
     fprintf(stderr, "Wake-up signal sent to group %ld.\n", *sh_temp);
     killpg(*sh_temp, SIGCONT);
 }

但是 - 如果有人有更好的解决方案请 post 它。

这似乎是为信号量量身定做的。具体来说,这很容易用 "System V semaphores" 实现。参见 semget(2)semop(2)

想法是在父级中获得一个信号量,将其值初始化为 N,然后让每个子级 "ready" 将值减 1。所有子级都等待结果变成 0。瞧。

这是一个示例程序

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define N       5

int main(int ac, char **av)
{
        int i, n, sem_id;
        sem_id = semget(IPC_PRIVATE, 1, 0777);

        struct sembuf buf;
        buf.sem_num = 0;
        buf.sem_flg = 0;

        // Initialize semaphore value to N
        buf.sem_op = N;
        n = semop(sem_id, &buf, 1);

        // All children will do the same thing:
        //    decrement semaphore value by 1
        //    wait for semaphore value == 0

        for (i = 0; i < N; ++i) {
                if (fork() == 0) {
                        printf("Child %d (%d) started\n", i, getpid());
                        sleep(i + 1);   // Sleep awhile.
                        buf.sem_op = -1;
                        n = semop(sem_id, &buf, 1);
                        buf.sem_op = 0;
                        n = semop(sem_id, &buf, 1);
                        printf("Child %d (%d) done\n", i, getpid());
                        return 0;
                }
        }
        return 0;
}