文章目录
- fork现象
- fork问题
fork现象
我们先来看一段代码。
大家觉得这段代码的printf会打印几次?
结果:
我们可以清楚的看到,第二个printf打印了2次。
我们再来看一段不可思议的代码:
运行结果:
我们可以看到这res竟然有两个值。
从上面我们可以得出结论,fork之后变成了两个进程一个是父进程,一个是子进程。
代码证明:
运行结果:
我们可以看到确实fork之后变成了两个进程。
由此我们可以的出结论:fork之后的代码是父子共享的,所以才会出现上面printf会被打印两次的现象。
我们创建子进程出来就是为了执行不同的代码逻辑,如果代码是共享的我们该如何执行不同的代码逻辑呢?
用以下方法解决:
之前我们学过fork在子进程和父进程中的返回值是不同的。
父进程:返回子进程pid
子进程:返回0
创建子进程失败:返回-1
接下来就是解决上面问题的方法:
用分支语句解决。
运行结果:
我们可以看到确实解决了上面的问题。
我们让他们一直循环,看两个进程会不会同时进行
运行结果:
我们在用监测指令,查看两个进程:
我们可以看到Linux中确实存在2个这样的进程,上面是父进程,下面是子进程。
上面说明了:fork之后有两个不同的执行流,各自ret在父子进程中是不一样的。
fork问题
问题一:为什么一份C语言代码,其中同一个变量会有不同的值?
下篇博客讲解
问题二:为什么给子进程返回的是0,给父进程返回的是子进程的pid
首先我们会理解一个事情:
父进程和子进程的比例一定是一比多的,我们可以理解为一个父亲可以有多个儿子,但是一个儿子一定只有一个父亲。
父进程 : 子进程 = 1 : n
其次举个例子:
比如张三有四个孩子子,为了区分他们,分别给孩子们取了名字,小明,小花,小华和小美。有一天小明的老师把张三叫到学校,说小明这次考试不好等等。张三回到家会叫小名你给我过来,还是会叫孩子你给我过来,肯定是叫名字因为有四个孩子如果叫孩子你给我过来歧义太大。
最后推广:
所以上面的例子推广到fork中,就明白为什么fork给父进程返回的是子进程的pid,是为了更好的区分他们。
问题三:为什么fork会有两个返回值?
首先我们要理解一个问题:
创建进程的时候,OS要做什么?
本质就是系统多了一个进程,所以OS要新建一个PCB(task_struc)来管理进程。
子进程PCB(task_struct)结构体的内部属性,要以父进程的PCB结构体为模板创建。
例子:比如你和你父母的DNA一定是相似度很高的。
其次我们要理解:
当fork已经准备return了,fork的核心代码执行完了吗?
我们都知道进程是用PCB结构体管理的,而PCB结构体是存放在链表中的,是以链表的形式管理起来的
那么CPU要调度进程是直接从链表中调度进程吗?
不是的,在Linux中还存在一种运行队列,当进程要被调度是先要被加载到运行队列中。
当进程加载到运行队列中执行完就会被干掉。
所以操作系统和CPU运行某个进程,本质从PCB结构体形成的队列中挑选一个PCB结构体,来执行它的代码和数据,进程调度变成了在PCB结构体的队列中选择一个进程的过程。
只要想到进程优先想到对应的PCB结构体。
而当fork准备return的时候,核心代码数据其实早已经跑完了。
当我们到return的时候其实,父进程和子进程早就已经进入到运行队列中。
所以当运行到return时父进程和子进程分别会执行自己return语句,所以就会有两个返回值。
问题四:fork()有两个返回值,意味着会被保存两次吗?
下次博客揭晓。
问题五:父子进程被创建出来了,哪一个进程先被运行完呢?
这个并不一定,因为一个进程并不一定会一直被CPU调度,可能CPU运行个10毫秒就继续运行另一个进程。
所以谁先被运行或者先运行完,由操作系统的调度器决定,不由人为决定。