调用fork()时,首先运行哪个进程

时间:2013-08-16 13:47:59

标签: linux process linux-kernel fork

我写了这个程序

main()
{
        int pid;
        pid=fork();
        if(pid==0)
                printf("\nI am child\n");
        else
                printf("\nI am parent\n");
}

执行时的输出是

 ./a.out 

I am parent

I am child

当我使用strace程序运行时,输出是[Last part]

arch_prctl(ARCH_SET_FS, 0x7fd1bbf52700) = 0
mprotect(0x7fd1bbd47000, 16384, PROT_READ) = 0
mprotect(0x7fd1bbf70000, 4096, PROT_READ) = 0
munmap(0x7fd1bbf54000, 103886)          = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd1bbf529d0) = 5109

I am child
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd1bbf6d000
write(1, "\n", 1
)                       = 1
write(1, "I am parent\n", 12I am parent
)           = 12
exit_group(13)                          = ?

输出显示父项首先运行,但是strace输出似乎表明子项首先运行,因为它首先打印。

规则是什么?

2 个答案:

答案 0 :(得分:3)

没有规则。一旦进程准备好执行(即fork系统调用返回),它就可以根据调度配置(优先级,选择的调度程序等)运行。根据进程如何添加到调度程序,可以在从fork返回后首先安排任一进程。 (并且,正如@nos在评论中所指出的,两个进程可以在多CPU /多核系统上同时运行。)

此外,在使用printf时,请记住,即使按固定规则调度进程,输出刷新也可能以不同的顺序发生。这就是为什么no-strace和strace运行之间的输出不同。

答案 1 :(得分:0)

在大多数情况下是父进程

fork()不是阻塞系统调用,因此除非父级已用完其调度量,否则它将继续在fork之后运行。子进程被放置在就绪列表中,并将由下一个可用的cpu运行,但父进程将在系统调用返回后立即运行。

以下是一个小程序产生的输出,它在10核笔记本电脑上运行10个子进程:

PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child
PARENT child PARENT child PARENT PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child
PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child
PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child

main() {
    int i;
    for (i=0; i<10; i++) {
        if (fork()) {
            write(1, "PARENT ", 7);
        }
        else {
            write(1, "child ", 6);
            exit(0);
        }
    }
}

编辑:但是,写一个阻止调用。更好的测试记录了子进程pid,并且还有子fork。如果父运行中没有子进程运行,它将分配连续的pid。这是一个连续20个分叉的行(换行符显示序列):

7824 7825
7827 7828 7829
7831 7832 7833 7834 7835 7836
7838 7839 7840 7841 7842 7843 7844 7845
7847

main() {
    int i;
    int pid, pids[1000];
    for (i=0; i<20; i++) {
        if (pid = fork()) {
            //write(1, "PARENT\n", 7);
            pids[i] = pid;
        }
        else {
            fork();
            //write(1, "child\n", 6);
            exit(0);
        }
    }
    for (i=0; i<20; i++) printf("%d\n", pids[i]);
}