【问题标题】:Wait for all processes reach some point in program, then resume等待所有进程到达程序中的某个点,然后恢复
【发布时间】:2015-08-19 00:09:49
【问题描述】:

我有一个通过 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

我不希望任何孩子放弃。

【问题讨论】:

  • 其实不是。我读过那个话题。作者希望“父进程仅在所有子进程都终止之后恢复执行(此 while 循环之后的点)。”我不想让我所有的孩子都在代码中的同一时刻。
  • 我的错。我没有标记它;)

标签: c linux synchronization fork


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您可以使用像信号量这样的同步结构。 在您要停止所有子代的代码处,让他们在信号量的队列中等待(在信号量上调用等待,初始值为 0),因此它们都会阻塞。

    然后您可以在父级中发出信号量,从而启动它们。

    【讨论】:

    • 信号量用于控制/授予对受限资源的访问权限。它不适用于该用例。
    • 为什么?我认为我们可以将信号量用作通用同步结构,并已在各种程序中使用。 Semaphore 是一个带有变量和队列的结构,据说它不能仅用于对资源的重新字符串访问。
    • 没错。您可以随心所欲地使用它。我的感觉仍然是,当您尝试使用信号量来实现它时,它被证明是一种“黑客行为”。我只是认为可能有一个更优雅的解决方案。例如,我想到了倒计时闩锁。不过你可能是对的……也许在 C 语言中没有太多的选择。
    【解决方案3】:

    我强烈推荐Message Passing Interface (MPI),因为它有MPI_Barrier,你可以用它来实现你想要的,几乎不需要你自己编码的逻辑。还有其他替代方案,例如 OpenMP。

    【讨论】:

    • 我将 OpenMPI 用于其他一些项目。在这一点上,类似 MPI 的解决方案是无用的。无论如何感谢您的回答。
    【解决方案4】:

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

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

    但是 - 如果有人有更好的解决方案,请发布。

    【讨论】:

      【解决方案5】:

      这似乎是为信号量量身定做的。具体来说,这很容易通过“System V 信号量”实现。请参阅 semget(2)semop(2)

      这个想法是,您在父级中获得一个信号量,将其值初始化为N,然后让每个“准备好”的子级将值减 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        • 2010-12-03
        • 2011-11-04
        • 2013-02-13
        • 1970-01-01
        • 2016-05-22
        相关资源
        最近更新 更多