C:fork()-子女和父母的行为不符合预期

时间:2019-02-21 05:31:23

标签: c process fork

我在fork()下的代码是一个创建其Child的进程,它们都调用相同的函数,该函数基本上会有一个循环。在内部,他们会在0到5之间随机睡眠几秒钟,然后打印一条愚蠢的消息,显示通过的过程已结束。最后,他们打印一条“正在退出”消息并离开。

问题在于,即使子级在完成之前仍是1或2遍,每次子级打印“退出”消息时,父级(显然)也会打印相同的消息。父项完成后,它将再次打印“退出”消息。如果父项在子项之前完成,它将在其完成时打印“退出”消息,并在子项完成时再次打印。

现在,如果我退出或返回Child if子句,则在函数执行完之后,将不显示“退出”父项消息。这使我相信孩子正在代表父母打印“退出”消息。那么,是什么导致父“退出”消息被打印两次?

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

const int PASS = 5;
const int RANDLIMIT = 5;
int i = 0;

void doSomeWork(char *who);

int main(int argc, char *argv[])
{
  printf("Just started, I am: %d\n", (int) getpid());
  pid_t pid = fork();
  printf("fork returned: %d\n", (int) pid);
  srand((int) pid);

  if (pid < 0) {
    perror("fork failed");
  } else if (pid == 0) {
    doSomeWork("Child");
    // if I exit(0) or return(0) here, it behaves accordingly.
  }
  doSomeWork("Parent");
  return(0);
}

void doSomeWork(char *who)
{
  int control = 0;
  for(; i < PASS; i++){
    sleep(rand() % RANDLIMIT);
    printf("%s: Done pass #%d\n", who, i);
  }
  printf("%s: exiting...\n", who);
}

孩子先完成:

[root@centos ~]# ./fork3
Just started, I am: 18232
fork returned: 18233
fork returned: 0
Child: Done pass #0
Parent: Done pass #0
Child: Done pass #1
Child: Done pass #2
Child: Done pass #3
Parent: Done pass #1
Parent: Done pass #2
Child: Done pass #4
Child: exiting...
Parent: exiting...
Parent: Done pass #3
Parent: Done pass #4
Parent: exiting...

父母先完成:

[root@centos ~]# ./fork3
Just started, I am: 19507
fork returned: 19508
Parent: Done pass #0
Parent: Done pass #1
fork returned: 0
Child: Done pass #0
Parent: Done pass #2
Parent: Done pass #3
Child: Done pass #1
Child: Done pass #2
Child: Done pass #3
Parent: Done pass #4
Parent: exiting...
[root@centos ~]# Child: Done pass #4
Child: exiting...
Parent: exiting...

1 个答案:

答案 0 :(得分:2)

您同时在父母和孩子的{em> 中呼叫doSomeWork("Parent")。这就是exit使之起作用的原因-然后孩子在调用doSomeWork("Parent")之前就终止了。

解决方案是:

if (pid < 0) {
    perror("fork failed");
} else if (pid == 0) {
    doSomeWork("Child");
} else {
    doSomeWork("Parent");
}

当然,请记住,两个进程同时运行,因此执行顺序是不可预测的(通常会遇到多任务处理问题)。