0

我写了这个程序

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

    return 0;
}

执行时的输出是

 ./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)                          = ?

输出显示 parent 首先运行,但 strace 输出似乎显示 child 先运行,因为它首先打印。

规则是什么?

4

2 回答 2

3

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

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

于 2013-08-16T13:51:56.827 回答
0

在大多数情况下,父进程

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

下面是一个小程序产生的输出,该程序分叉 10 个子进程,在 2 核笔记本电脑上运行:

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

编辑:但是, write一个阻塞调用。更好的测试记录子进程 ​​pid,并且也有子进程。如果父进程之间没有子进程运行,它将分配连续的 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]);
}
于 2014-12-27T04:33:38.063 回答