今天学习操作系统的时候对于创建子进程的fork()语句理解起来有些困难,搜索之后发现这两篇结合代码分析的博客思路很清晰易懂,特此整合成一篇。仅做学习交流用途!
1.一次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);
}
else if(pid > 0)
{
printf("this is father process, pid is %d\n",getpid());
count++;
printf("count = %d\n",count);
}
else
{
fprintf(stderr,"ERROR:fork() failed!\n");
}
return 0;
}
fork的时候发生什么?
1.执行到这一句的时候,一个子进程被创建了,这个进程与父进程一样,拥有一套与父进程相同的变量,相同的一套代码,这里可以粗浅的理解为子进程又复制了一份main函数。这里返回一个子进程的进程号,大于0。(第一次fork)
2.子进程怎么执行:
子进程从fork()的位置开始执行,也就是说前面的代码不走,但是拥有之前的变量以及变量的值,与父进程的值一样,这次fork(),返回值是0,所以在子进程里面直接执行了pid==0这一个分支,父进程里面并不执行这个分支的语句。这就为我们在写mian函数的时候怎么写子进程的程序提供了一个方法来隔离代码。
2.两次fork():
#include "csapp.h" int main() {
fork(); //位置1·
fork(); //位置2
printf("hello/n");
exit(0); }
//结果打印出4个hello;
为什么会这样呢?
原来在创建子程序时,子程序会得到父程序的一份拷贝,那么其中也包括下一条指令指针。具体如下:
开始只有一个父进程;
父进程执行完第一个fork()(这时下一条指令指针变成位置2)。
创建出的一个子进程(这个进程也会从位置2开始执行)
所以这个子进程会又创建一子子进程;(这时就有两个子进程了)
父进程再执行第二个fork();
又会创建一个子进程(这时就三个子进程了)
加上父进程一共四个,所以输出4个hello world;
3.三次fork()
明白了这个原理之后我们再来看一段代码
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid[3];
int count = 0;
pid[0] = fork();
pid[1] = fork();
pid[2] = fork();
printf("this is process\n");
return 0;
}
运行结果
这里附上思维导图助于理解
4. 补充
今天上了操作系统课,通过几个例题又有了新的体会:
这里需要注意一点,对于第一条语句,先执行fork()操作,再进行print。
具体思路如下(进程家族树):
(红色数字为每个进程打印的次数)
因此,共八个进程(包括main函数),打印14条语句。
注意:子进程在创建过程中复制了父进程的资源,因此单独的对子进程/父进程的操作对另一方不会造成改变。
因此结果输出为:5
关于父子进程之间的资源共享问题,可以参考下面这篇博文:https://www.cnblogs.com/xuelisheng/p/10072065.html
#END
#update 2020.3.2