C: 为什么 fork() 之后 child 块不是 运行?
C: why after fork() child block is not running?
我正在研究 fork() 的实际工作原理,所以我下面的代码除了使用 fork() 生成新进程并看到它们随机死掉外没有其他用途。所以:
- 我将我的 fork() 放在一个 for 循环中(现在到 运行 两次)看到创建了多个 child,令我惊讶的是第二个 Child 有一个 parent 与第一个 child 不同 parent。因此,如果我的初始 PID 是 1000,则创建的两个 child 将是 1002(child of 1000)和 1003(child of 1001 ???)。我不明白创建 parent 是怎么回事。 This guy解释了,但我不能说我完全理解。
- 为了找出发生了什么,我打印了我的 parent(和 child)进程及其 PID,但是如果我为我的 parent 声明一个字符,我的 child 不会 运行 该功能。我在
<<< >>>
. 之间的代码中解释了我的意思
那么,谁能帮助我理解第 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 下面的建议,看起来很不错。
- 您不能在循环中调用
fork()
,如果您希望程序运行,则只能在循环结束时检查 returns 是什么。当您这样做时,您将启动指数级数量的子进程,并且每个子进程都认为它是 "the parent",只要它是其最终 fork() 的父进程即可。将 pid
的测试移到循环内。
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
.
例子
- Parent 进程
pid=1000
i = 0
,创建 pid=1001
,现在您同时拥有 1000
和 1001
i = 1
,从 1001
创建一个 child -> 1002
并再次从 1000
创建一个 child,1003
.
最后你有 1000
, 1001
, 1002
和 1003
这四个进程都会 运行 下面的指令是printf
。
我正在研究 fork() 的实际工作原理,所以我下面的代码除了使用 fork() 生成新进程并看到它们随机死掉外没有其他用途。所以:
- 我将我的 fork() 放在一个 for 循环中(现在到 运行 两次)看到创建了多个 child,令我惊讶的是第二个 Child 有一个 parent 与第一个 child 不同 parent。因此,如果我的初始 PID 是 1000,则创建的两个 child 将是 1002(child of 1000)和 1003(child of 1001 ???)。我不明白创建 parent 是怎么回事。 This guy解释了,但我不能说我完全理解。
- 为了找出发生了什么,我打印了我的 parent(和 child)进程及其 PID,但是如果我为我的 parent 声明一个字符,我的 child 不会 运行 该功能。我在
<<< >>>
. 之间的代码中解释了我的意思
那么,谁能帮助我理解第 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 下面的建议,看起来很不错。
- 您不能在循环中调用
fork()
,如果您希望程序运行,则只能在循环结束时检查 returns 是什么。当您这样做时,您将启动指数级数量的子进程,并且每个子进程都认为它是 "the parent",只要它是其最终 fork() 的父进程即可。将pid
的测试移到循环内。
那会破坏一些随机记忆。您需要先将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
.
例子
- Parent 进程
pid=1000
i = 0
,创建pid=1001
,现在您同时拥有1000
和1001
i = 1
,从1001
创建一个 child ->1002
并再次从1000
创建一个 child,1003
.
最后你有 1000
, 1001
, 1002
和 1003
这四个进程都会 运行 下面的指令是printf
。