C: 为什么 fork() 之后 child 块不是 运行?

C: why after fork() child block is not running?

我正在研究 fork() 的实际工作原理,所以我下面的代码除了使用 fork() 生成新进程并看到它们随机死掉外没有其他用途。所以:

  1. 我将我的 fork() 放在一个 for 循环中(现在到 运行 两次)看到创建了多个 child,令我惊讶的是第二个 Child 有一个 parent 与第一个 child 不同 parent。因此,如果我的初始 PID 是 1000,则创建的两个 child 将是 1002(child of 1000)和 1003(child of 1001 ???)。我不明白创建 parent 是怎么回事。 This guy解释了,但我不能说我完全理解。
  2. 为了找出发生了什么,我打印了我的 parent(和 child)进程及其 PID,但是如果我为我的 parent 声明一个字符,我的 child 不会 运行 该功能。我在 <<< >>>.
  3. 之间的代码中解释了我的意思

那么,谁能帮助我理解第 1 点,并确定为什么会出现第 2 点?

完整代码如下:

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

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

void doSomeWork(char *who);

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

  for (j=0; j < FORKNUMBER; j++)
    pid = fork();

  printf("fork returned: %d\n", (int) pid);
  srand((int) pid + rand());

  if (pid < 0) {
    perror("fork failed");
  } else if (pid == 0) {
    char * childPid;
    char * childName;
    sprintf(childPid, "%d", (int) getpid());
    childName = (char *) malloc(strlen("Child - ") + strlen(childPid) + 1 );
    strcpy(childName, "Child - ");
    strcat(childName, childPid);
    doSomeWork(childName);
    exit(0);
  }

  //<<< The malloc above for the child to send a parameter >>>
  //<<< to the function, works fine. But when I try to do  >>>
  //<<< the same for my parent, the simple declaration of a>>>
  //<<< char below, makes the child block (the if PID==0)  >>>
  //<<< not run. The 3 lines commented below were an       >>>
  //<<< attempt to understand what was preventing the child>>>
  //<<< block from running. Now, if the parent calls the   >>>
  //<<< function with a string not declared before, the    >>>
  //<<< child block runs fine.>>>

  //char parentName[strlen("Parent") + 1];
  //strcpy(parentName, "Parent");
  //doSomeWork(parentName);
  doSomeWork("Parent");
  //wait(NULL);
  return(0);
}

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

    if (control == 0)
    {
      char childWord[6];
      strncpy(childWord, who, 5);

      if (strcmp(childWord, "Child") == 0 && (int) getppid() == 1 )
      {
        control = 1;
        printf("%s: became orphan at #%d\n", who, i);
      }
    }
  }
  printf("%s: exiting...\n", who);
}

编辑:

对于 1,我创建了如下函数:

int nbDigits(int number)
{
  int i=0;
  for(; number > 10; i++)
  {
    number /= 10;
  }
  return ++i;
}

现在,我不再像这样声明一个指向 char 的指针,char * childPid; 我像这样声明一个 char 数组 char childPid[nbDigits(getpid()) + 1];,一切都很顺利。

使用 asprintf() 查看 Joseph 下面的建议,看起来很不错。

  1. 您不能在循环中调用 fork(),如果您希望程序运行,则只能在循环结束时检查 returns 是什么。当您这样做时,您将启动指数级数量的子进程,并且每个子进程都认为它是 "the parent",只要它是其最终 fork() 的父进程即可。将 pid 的测试移到循环内。
  2. char * childPid;
    sprintf(childPid, /* ... */);
    
    那会破坏一些随机记忆。您需要先将 childPid 指向某些东西,然后再 sprintf 指向它,或者将 sprintf 替换为 asprintf 之类的东西,它将自行分配。

只要您 运行 fork() 任何 child 进程就会从那里开始执行。

Fork system call use for creates a new process, which is called child process, which runs concurrently with process (which process called system call fork) and this process is called parent process. After a new child process created, both processes will execute the next instruction following the fork() system call. source

因此,当你的第一次迭代发生时 (i=0) 会有一个新的过程,有一个新的 pid,然后 parent 和这个 child 过程将调用下一次迭代 (i=1) 并为每个迭代创建一个新的 child 以及另外两个新的 pid。最后,您将有 4 个不同的 pid.

例子

  1. Parent 进程 pid=1000
  2. i = 0,创建 pid=1001,现在您同时拥有 10001001
  3. i = 1,从 1001 创建一个 child -> 1002 并再次从 1000 创建一个 child,1003.

最后你有 1000, 1001, 10021003 这四个进程都会 运行 下面的指令是printf