今天一个考研复试的同学问我一个问题:
感觉对 fork 的理解挺有代表性的。
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int count = 0;
pid = fork(); //fork一个进程
if(pid == 0)
{ //pid为0,
printf("this is child process, pid is %d\n",getpid()); //getpid返回的是当前进程的PID
count += 2;
printf("count = %d\n",count);
return 0;
}
else if(pid > 0)
{
printf("this is father process, pid is %d\n",getpid());
count++;
printf("count = %d\n",count);
return 0;
}
else
{
fprintf(stderr,"ERROR:fork() failed!\n");
}
return 0;
}
这是一个简单的 fork 调用函数说明 pid 为 0 即进入的是子进程的逻辑, pid > 0 则表示进入父进程。
一般在多进程编程时,会将 fork 的返回值来做判断进入的是哪个进程。(ps 我现在用得更多是多线程并发)
[kywlzr@localhost test_fork]$ gcc test_fork.c -o test_fork
[kywlzr@localhost test_fork]$
进行编译,得到 test_fork 函数,执行一下
this is father process, pid is 3106
count = 1
[kywlzr@localhost test_fork]$ this is child process, pid is 3107
count = 2
可以看到父子进程的 pid 是不一样的
然后再来看看题目这个写法:
1 #include<stdio.h>
2 #include<unistd.h>
3
4 int main()
5 {
6 pid_t pid[3];
7 pid[0] = fork();
8 pid[1] = fork();
9 pid[2] = fork();
10 sleep(100);
11 printf("this is process\n");
12
13 return 0;
14 }
15
16
一样编译一下
[kywlzr@localhost test_fork_2]$ gcc test_fork_2.c -o test_fork_2
[kywlzr@localhost test_fork_2]$
再运行
[kywlzr@localhost test_fork_2]$ ./test_fork_2
再来看看名字叫 test_fork_2 的进程有几个
[kywlzr@localhost ~]$ ps -ef | grep test_fork_2 | grep -v grep
kywlzr 3190 3060 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3191 3190 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3192 3190 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3193 3190 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3194 3192 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3195 3191 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3196 3191 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3197 3195 0 18:08 pts/2 00:00:00 ./test_fork_2
没错,就是有 8 个,其中有 3 个的父进程都是 3190,有两个的父进程是 3191。
3190 就是最开始这个进程
第一次调用 fork() ,产生第一个子进程 3191,这个时候 3190 和 3191 都继续执行剩余的两次 fork()(代码 8 9 行)
3190 又产生一个子进程 3192;
3191 产生的子进程是 3195;
最后 3190 3191 3192 3195 都在执行第 9 行的 fork() 函数
3190 产生 3193
3192 产生 3194
3192 产生 3196
3195 产生 3197
过程参考此图
那这就有一个问题了,进程号的顺序应该是按执行的先后顺序安排的,那为什么 3192 进程会在 3191 之前执行呢?
我猜这是个栈?可以看看 fork 4次的结果
[kywlzr@localhost ~]$ ps -ef | grep test_fork_2 | grep -v grep
kywlzr 3256 3060 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3257 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3258 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3259 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3260 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3261 3259 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3262 3258 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3263 3258 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3264 3257 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3265 3257 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3266 3257 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3267 3262 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3268 3264 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3269 3264 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3270 3265 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3271 3268 0 18:31 pts/2 00:00:00 ./test_fork_2
验证了我的猜想= =但是 3257 这个进程有点怪,它的子进程是 3264 3265 3266 为什么不是 3265 先创建子进程,而是 3264 先创建??(留个坑)
如果想创建三个子进程呢?
#include <stdio.h>
#include <stdlib.h>
#include <sys/unistd.h>
int main(int argc, char *argv[])
{
int i,j,status;
int pid[3];
for(i = 0; i < 3; i++)
{
if((pid[i] = fork()) >0)
{
printf("This is child process pid=%d\n",pid[i]);
}
else
{
printf("This is father process pid=%d\n",pid[i]);
exit( 0);
}
}
return 0;
}
输出结果:
[kywlzr@localhost test_fork_3]$ ./test_fork_3
This is child process pid=2618
This is child process pid=2619
This is child process pid=2620
[kywlzr@localhost test_fork_3]$ This is father process pid=0
This is father process pid=0
This is father process pid=0