当前位置: 技术问答>linux和unix
初学操作系统,对于fork()函数有多处不理解,拜求大家赐教
来源: 互联网 发布时间:2017-01-23
本文导语: 先举个最简单的实例 #include main(){ printf("公共程序段"); int p1=fork(); if(p1==0) printf("子程序段"); else printf("父程序段"); } 大家都知道,fork函数在此处有个现象,就是执行一次,返回两次。 在这里我起初对于如何实...
先举个最简单的实例
#include
main(){
printf("公共程序段");
int p1=fork();
if(p1==0)
printf("子程序段");
else
printf("父程序段");
}
大家都知道,fork函数在此处有个现象,就是执行一次,返回两次。
在这里我起初对于如何实现执行一次,返回两次有疑问,既然子进程中有fork这段代码,那就应该是执行两次,返回两次,也就是说子进程会再通过fork创建自己的子进程,如此循环往复,直到达到系统的进程表的上限。
后来,我通过查阅资料,对这个机制有了进一步理解。
进程映像分为三部分:可执行程序、数据、和进程控制块中的上下文等信息。而操作系统为了实现多进程并发执行,就采用一系列调度算法,进程就不得不在执行过程中断断续续,进程在让出CPU后等待一段时间再一次轮到自己执行时,系统必须知晓它上次停下之前执行到哪里了,记录这个信息并不难,因为程序在运行时有个寄存器,大概叫程序寄存器记录了下一条要执行的指令所在的地址,所有在程序不得不停下让出时间片时,系统就把那个程序寄存器中的地址记录到进程页中,下一次再轮到那个进程执行时不至于把那个进程从头开始执行,而是从上次停下的地方执行。
那么再回到进程创建的问题。
我例子中的程序,执行到int p1=fork()的时候,我理解中是fork内部可以宏观的分为两部分:1、创建子进程;2、返回所创建的进程的进程号。
当父进程执行到fork内部的第一部分时,即创建了进程,但是尚未返回子进程的进程号时,进程控制块中一直都实时记录这进程运行到了哪里,当然此时的记录是“该进程运行到了fork函数的第一层,尚未返回”。这里问题的关键出来了,子进程是按照父进程的模板刻画的,它现在已经在进程页表里面了,下一步就轮到它执行了,最精彩的部分开始出现了,它的页表项信息中居然记录这这样一条信息“该进程已经运行到fork函数的第一层,尚未返回”,所以,当时间片轮到子进程的时候,它直接就按照记录执行下一步,既然fork的创建工作已经执行了,那我就直接返回。通俗的说,子进程不是从头开始执行程序的代码段,而是从“fork函数返回”这里开始执行的,这样子就可以解释为什么fork函数只执行一次,而返回两次,因为在子进程中它没有执行创建子进程的工作,而是直接返回了0。
但是,新的问题又出现了,如果按照我上述那么理解,那么子进程就不会执行公共程序段printf("公共程序段");
所以我上面的理解一定是错误的,或者有相当大的问题的,请大侠们指正,只需回答我三个疑点:
一、为什么子进程中的fork不会再创建新的进程
(如果你的回答是fork执行一次,返回两次,那么请看下面问题)
二、fork为什么会执行一次,返回两次呢,这是什么机制实现的
#include
main(){
printf("公共程序段");
int p1=fork();
if(p1==0)
printf("子程序段");
else
printf("父程序段");
}
大家都知道,fork函数在此处有个现象,就是执行一次,返回两次。
在这里我起初对于如何实现执行一次,返回两次有疑问,既然子进程中有fork这段代码,那就应该是执行两次,返回两次,也就是说子进程会再通过fork创建自己的子进程,如此循环往复,直到达到系统的进程表的上限。
后来,我通过查阅资料,对这个机制有了进一步理解。
进程映像分为三部分:可执行程序、数据、和进程控制块中的上下文等信息。而操作系统为了实现多进程并发执行,就采用一系列调度算法,进程就不得不在执行过程中断断续续,进程在让出CPU后等待一段时间再一次轮到自己执行时,系统必须知晓它上次停下之前执行到哪里了,记录这个信息并不难,因为程序在运行时有个寄存器,大概叫程序寄存器记录了下一条要执行的指令所在的地址,所有在程序不得不停下让出时间片时,系统就把那个程序寄存器中的地址记录到进程页中,下一次再轮到那个进程执行时不至于把那个进程从头开始执行,而是从上次停下的地方执行。
那么再回到进程创建的问题。
我例子中的程序,执行到int p1=fork()的时候,我理解中是fork内部可以宏观的分为两部分:1、创建子进程;2、返回所创建的进程的进程号。
当父进程执行到fork内部的第一部分时,即创建了进程,但是尚未返回子进程的进程号时,进程控制块中一直都实时记录这进程运行到了哪里,当然此时的记录是“该进程运行到了fork函数的第一层,尚未返回”。这里问题的关键出来了,子进程是按照父进程的模板刻画的,它现在已经在进程页表里面了,下一步就轮到它执行了,最精彩的部分开始出现了,它的页表项信息中居然记录这这样一条信息“该进程已经运行到fork函数的第一层,尚未返回”,所以,当时间片轮到子进程的时候,它直接就按照记录执行下一步,既然fork的创建工作已经执行了,那我就直接返回。通俗的说,子进程不是从头开始执行程序的代码段,而是从“fork函数返回”这里开始执行的,这样子就可以解释为什么fork函数只执行一次,而返回两次,因为在子进程中它没有执行创建子进程的工作,而是直接返回了0。
但是,新的问题又出现了,如果按照我上述那么理解,那么子进程就不会执行公共程序段printf("公共程序段");
所以我上面的理解一定是错误的,或者有相当大的问题的,请大侠们指正,只需回答我三个疑点:
一、为什么子进程中的fork不会再创建新的进程
(如果你的回答是fork执行一次,返回两次,那么请看下面问题)
二、fork为什么会执行一次,返回两次呢,这是什么机制实现的
|
这个确实不好理解
初学只需要记住,从fork返回开始,就根据返回值当作两个程序来对待
至于fork返回之后,是父进程先执行,还是子进程先执行,这个不一定的
初学只需要记住,从fork返回开始,就根据返回值当作两个程序来对待
至于fork返回之后,是父进程先执行,还是子进程先执行,这个不一定的
|
fork是个系统调用,进入内核,内核就会生成子进程,这个时候不是什么fork执行一次,返回两次,而是父子进程各返回一次,只是内核把父子进程从fork返回的返回值设置得不同而已。