【问题标题】:Why aren't my processes running concurrently?为什么我的进程没有同时运行?
【发布时间】:2012-08-31 23:40:44
【问题描述】:

我的问题是:

1.) 我怎样才能让父进程总是最后死掉?我知道这没有完成,因为父进程是第一个运行的 pid,但我不知道如何更改它。

2.) 如何让我的子进程像他的一样同时执行?我什至把这个数字提高了很多,看看这是否只是巧合,但似乎不是。

编辑:解决方案

1.) 在内部默认值中添加了两次 wait(NULL)
2.) 正在发生。用 sleep(1) 来证明。

我的代码如下

#include <stdio.h>
int main() {
    int pid, i;
    pid = fork();
    switch(pid) {
        case -1:
            // error
            printf("Fork error");
            break;
        case 0:
            // child process
            printf("First child is born, my pid is %d\n", getpid());
            for(i=1; i<10; i++)
                printf("First child executes iteration %d\n", i);
            printf("First child dies quietly.\n");
            break;
        default:
            // parent process
            printf("Parent process is born, my pid is %d\n", getpid());
            pid = fork();
            switch(pid) {
                case -1:
                    // error
                    printf("Fork error");
                    break;
                case 0:
                    // child process
                    printf("Second child is born, my pid is %d\n", getpid());
                    for(i=1; i<10; i++)
                        printf("Second child executes iteration %d\n", i);
                    printf("Second child dies quietly.\n");
                    break;
                default:
                    // parent process
                    printf("Parent process dies quietly.");
        }
    }
    return 0;
}

我的输出总是这样:

父进程诞生,我的pid是7847 第一个孩子出生,我的pid是7848 第一个孩子执行迭代:1 第一个孩子执行迭代:2 第一个孩子执行迭代:3 第一个孩子执行迭代:4 第一个孩子执行迭代:5 第一个孩子执行迭代:6 第一个孩子执行迭代:7 第一个孩子执行迭代:8 第一个孩子执行迭代:9 第一个孩子执行迭代:10 第一个孩子安静地死去。 父进程静静地死去。 第二个孩子出生了,我的pid是7849 第二个孩子执行迭代 1 第二个孩子执行迭代 2 第二个孩子执行迭代 3 第二个孩子执行迭代 4 第二个孩子执行迭代 5 第二个孩子执行迭代 6 第二个孩子执行迭代 7 第二个孩子执行迭代 8 第二个孩子执行迭代 9 第二个孩子执行迭代 10 第二个孩子安静地死去。

我的任务是:

编写一个创建三个进程的 C 程序(“procs.c”):一个创建两个子进程的父进程。

第一个孩子应该做以下事情:

  • 显示“第一个孩子出生,我的 pid 是...”

  • 显示十次消息“第一个孩子执行迭代 X”,其中 X 是迭代次数

  • 显示“第一个孩子安静地死去。”

第二个孩子应该做以下事情:

  • 显示“第二个孩子出生了,我的pid是……”

  • 显示十次消息“第二个孩子执行迭代X”,其中X是迭代次数

  • 显示“第二个孩子安静地死去。”

父进程应该做以下事情:

  • 显示“父进程诞生,我的pid是……”

  • 创建第一个孩子

  • 创建第二个孩子

  • 显示“父进程安静地死掉。”

使用 gcc 编译程序并将可执行文件命名为“procs”。多次执行程序,注意两个孩子的输出是如何交错的。

这个程序的一个可能的输出是:

新星> ./procs 父进程诞生,我的pid是7847 第一个孩子出生,我的pid是7848 第一个孩子执行迭代:1 第一个孩子执行迭代:2 第一个孩子执行迭代:3 第一个孩子执行迭代:4 第一个孩子执行迭代:5 第二个孩子出生了,我的pid是7849 第二个孩子执行迭代 1 第二个孩子执行迭代 2 第二个孩子执行迭代 3 第一个孩子执行迭代:6 第二个孩子执行迭代 4 第二个孩子执行迭代 5 第二个孩子执行迭代 6 第一个孩子执行迭代:7 第二个孩子执行迭代 7 第二个孩子执行迭代 8 第二个孩子执行迭代 9 第二个孩子执行迭代 10 第二个孩子安静地死去。 第一个孩子执行迭代:8 第一个孩子执行迭代:9 第一个孩子执行迭代:10 第一个孩子安静地死去。 父进程静静地死去。

【问题讨论】:

    标签: c process fork pid


    【解决方案1】:

    fork() 创建一个新的子进程,它独立于父进程运行。

    如果你想让父进程等待子进程完成,你可以使用系统调用wait,传递一个PID,它会阻塞直到进程完成。

    见文章wait(System Call) on Wikipedia

    【讨论】:

      【解决方案2】:
      1. 适当的父进程应等待(使用wait() or waitpid() 或特定于平台的变体)其子进程在退出之前死亡。

      2. 并发执行需要调度程序有机会运行。您可以通过适当的睡眠(微睡眠,nano-sleep)操作来强制解决问题。一些系统调用会有所帮助(所以fflush(0) 可能会有所帮助)。


      #include <stdio.h>
      #include <sys/wait.h>
      #include <time.h>
      #include <unistd.h>
      
      int main(void)
      {
          int pid, i;
          struct timespec tw = { .tv_sec = 0, .tv_nsec = 10000000 };
          pid = fork();
          switch(pid)
          {
              case -1:
                  printf("Fork error");
                  break;
              case 0:
                  printf("First child is born, my pid is %d\n", getpid());
                  for(i=1; i<10; i++)
                  {
                      printf("First child executes iteration %d\n", i);
                      nanosleep(&tw, 0);
                  }
                  printf("First child dies quietly.\n");
                  break;
              default:
                  printf("Parent process is born, my pid is %d\n", getpid());
                  pid = fork();
                  switch(pid)
                  {
                      case -1:
                          printf("Fork error");
                          break;
                      case 0:
                          printf("Second child is born, my pid is %d\n", getpid());
                          for(i=1; i<10; i++)
                          {
                              printf("Second child executes iteration %d\n", i);
                              nanosleep(&tw, 0);
                          }
                          printf("Second child dies quietly.\n");
                          break;
                      default:
                          printf("Parent process waiting for children.\n");
                          int corpse;
                          int status;
                          while ((corpse = waitpid(0, &status, 0)) > 0)
                              printf("Child %d died with exit status 0x%.4X\n", corpse, status);
                          printf("Parent process dies quietly.\n");
                          break;
                  }
          }
          return 0;
      }
      

      示例输出:

      Parent process is born, my pid is 46624
      First child is born, my pid is 46625
      First child executes iteration 1
      Parent process waiting for children.
      Second child is born, my pid is 46626
      Second child executes iteration 1
      First child executes iteration 2
      Second child executes iteration 2
      First child executes iteration 3
      Second child executes iteration 3
      First child executes iteration 4
      Second child executes iteration 4
      Second child executes iteration 5
      First child executes iteration 5
      Second child executes iteration 6
      First child executes iteration 6
      Second child executes iteration 7
      First child executes iteration 7
      Second child executes iteration 8
      First child executes iteration 8
      Second child executes iteration 9
      First child executes iteration 9
      First child dies quietly.
      Second child dies quietly.
      Child 46625 died with exit status 0x0000
      Child 46626 died with exit status 0x0000
      Parent process dies quietly.
      

      请注意,10 毫秒的延迟几乎会强制交替执行。如果没有类似的东西,您就会被系统及其调度程序的特性所困扰,而且许多现代机器都太快了!

      【讨论】:

      • 我的书有一个和我一样的例子,除了默认也有一个 for 循环。结果通常看起来像 parent1、parent2、child1、child2、child3、child4、parent3 等。在我的情况下,为什么第二个孩子没有在第一个孩子的执行过程中开始执行?
      • 谢谢。您的帮助启发了我在我的子进程中加入 sleep(1) 以证明它们同时运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-05
      • 1970-01-01
      • 2013-05-08
      • 1970-01-01
      相关资源
      最近更新 更多