子进程在父进程启动后开始运行

8

我有一个简单的代码用来测试fork()函数。

    #include<stdio.h>
    #include<unistd.h>
    #define MAX_COUNT 10
    void main(void)
    {
        pid_t pid;
        int i;
        fork();
        pid = getpid();
        for(i = 1; i <= MAX_COUNT; i++)
        {
            printf("PID = %d, i = %d\n", pid, i);
        }
    }

它没有按照我预期的工作。

我的期望是:父级和子级的结果交替出现。

有人能解释一下并教我如何修复吗?谢谢!

    PID = 3663, i = 1
    PID = 3663, i = 2
    PID = 3663, i = 3
    PID = 3663, i = 4
    PID = 3663, i = 5
    PID = 3663, i = 6
    PID = 3663, i = 7
    PID = 3663, i = 8
    PID = 3663, i = 9
    PID = 3663, i = 10
    PID = 3664, i = 1
    PID = 3664, i = 2
    PID = 3664, i = 3
    PID = 3664, i = 4
    PID = 3664, i = 5
    PID = 3664, i = 6
    PID = 3664, i = 7
    PID = 3664, i = 8
    PID = 3664, i = 9
    PID = 3664, i = 10

7
这两个过程是独立运行的,因此一旦发生分叉,您不能期望有任何特定的顺序(这取决于操作系统调度)。如果您想要一个特定的顺序,您必须使用同步机制显式地自己完成。例如:等待、信号量、互斥锁、管道等。 - kaylum
我指的当然是进程之间的排序。进程内部的排序自然而然地被定义清楚了。 - kaylum
如果你的目标只是测试fork()并进行探索,那么在其中加入一些睡眠时间是很正常的做法。我相信在这个上下文中,“alternatingly”实际上意味着非顺序执行。 - QuestionC
什么让你期望调度程序提供保证? - Charles Duffy
@QuestionC 已收到 - Eli Algranti
显示剩余3条评论
2个回答

11
解释很简单。 进程调度由内核决定。如果这是一个单核处理器,那么在此运行中,它决定暂停子执行并允许父进程先运行。父进程在被挂起之前运行了几个循环,依此类推。
在多处理器系统中,两个进程都可以同时运行,但控制台设备会根据中断的时间间隔交替输出。
不能保证不同的运行将导致相同的输出。也不能保证不同的内核版本不会做其他事情。
如果你想让进程在循环之间交替运行,现在就是学习进程间通信的时候了。点这里学习。

通常情况下,您可以期望内核在调度进程时是“公平”的。这意味着,如果父进程和子进程运行了很长时间,它们都将获得大致相同的处理时间,并且在激活之间不必等待太长时间。当然,这里考虑的时间尺度远远大于几个循环迭代。 - MicroVirus

2
主进程并不会立即放弃控制权,而for循环执行得非常快,在第二个进程被调度之前就完成了。当我执行你的代码时,我得到了非顺序的打印输出,但这种行为取决于系统。
在使用fork()时,有时候在代码中加入sleep()命令是有帮助的。请尝试以下代码...
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX_COUNT 10
int main(void)
{
  pid_t pid;
  int i;
  fork();

  pid = getpid();

  srand(pid); // Make sure each process has a different seed

  for(i = 1; i <= MAX_COUNT; i++)
  {
    printf("PID = %d, i = %d\n", pid, i);

    // Sleep 1-3 seconds.
    unsigned int sleep_seconds = rand() % 3 + 1;
    sleep(sleep_seconds);
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接