理解fork()的一次调用两次执行
来源:互联网 发布:linux常用网络命令大全 编辑:程序博客网 时间:2024/05/19 04:53
fork()函数是linux里多进程编程的基础,为linux成为强大的多用户操作系统提供了强有力的支持。
但是对于很多初学者而言,虽然知道怎么写多进程的程序,知道怎么fork()出一个子进程,却很少有人能够理解fork()的最有特点的一个性质:一次调用,两次执行。
进程在内存里有三部分的数据——代码段、堆栈段和数据段。这三个部分是构成一个完整的执行序列的必要的部分。
代码段——存放了程序代码的内存空间。这个最容易理解,不就是程序在机器内的表示而已嘛。注意假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。也就是说如果fork()出来了一个子进程,子进程和父进程实际上使用的是相同的代码段。
堆栈段——存放的就是子程序的返回地址、子程序的参数以及程序的局部变量。比如说写了这样一个程序:
int a;void main(){int b;int c=func();}int func(){int d;return 0;}这个程序里哪些变量是存放在堆栈段里的呢?不考虑编译器优化,实际上变量b,c,d都是会存放在堆栈里的。而a则会存放在接下来说的数据段里。
数据段——存放程序的全局变量,常数以及动态数据分配的数据空间(比如用malloc之类的函数取得的空间)。
好了,知道了上面三个段之后有什么用呢?用处可大了,这就说明了系统中的每一个进程都需要由这三个段来组成。不管是父进程还是fork()出来的子进程。但是上面也提到,由于子进程和父进程运行的是同样的程序(只是程序里的不同部分),它们使用相同的代码段,但是会拥有各自的数据段和堆栈段。
我们通常会这样写一个程序:
void main(){pid_t pid;pid=fork();if(pid==0){//子进程任务}else if(pid>0){//父进程任务}}执行过程是这样的:
1.操作系统分配内存给父进程,包括上面提到的三个段,就是会在堆栈段里有一块空间是用来存放pid变量的。
2.接着内核调度父进程执行fork()函数(这个函数里实际上使用了系统调用),这时候子进程才会出现,内核会将父进程的数据段和堆栈段作一个拷贝给子进程,注意这时子进程的堆栈段里一定会有一个空间用来存放pid变量!然后系统调用成功,内核给父进程堆栈段里的pid变量赋上子进程的pid号,而给子进程堆栈段里的pid变量赋上0。
3.接下来还是交给内核调度决定执行的是子进程还是父进程(一般内核会先给子进程执行)。如果是父进程,它的下一句代码就是判断pid变量的大小,它会去它的堆栈段里存放pid变量的地方取出pid来进行比较,它会发现pid>0,所以接下来它就去执行——父进程任务;如果是子进程,由于同样的代码段,它也会去比较它自己的pid变量,发现pid=0,所以接下来它会去执行——子进程任务。
注:左边父进程,右边子进程
这样,fork()函数就实现了一次调用,两次执行。关键就是在于父子进程拥有不同的堆栈段,而内核给这两个堆栈段里的pid赋上不同的值。
最后,我们来看看编译后的汇编程序,就能证实我的说法,也能更好地理解。
esp是堆栈指针寄存器,可以看到,在调用fork()函数之后将28(%esp)和0进行了比较,显然,28(%esp)就是pid变量。它存放在堆栈段里。
- 理解fork()的一次调用两次执行
- 理解fork()的一次调用两次执行
- 理解多进程fork函数调用一次返回两次
- fork() 一次调用两次返回。
- 守护进程(精灵进程)&调用fork一次和两次的区别
- 创建守护进程fork一次与fork两次的区别
- 一次调用,两次返回--fork函数学习总结
- 守护进程中fork一次与两次的区别
- 守护进程 & 创建守护进程 & fork一次和fork两次的区别
- 守护进程 & 创建守护进程 & fork一次和fork两次的区别
- 守护进程&创建守护进程&fork一次和fork两次的区别
- Linux--进程组,会话,精灵进程(fork一次与fork两次的区别)
- 两次fork函数可以防止进程僵死的理解
- 调用fork两次以避免僵死进程的产生
- 一次请求 服务端执行两次
- daemon进程fork一次和fork两次区别
- 点击一次pushButton会对相应的slot执行两次
- Struts2 请求一次Action,却执行两次方法的解决
- Dijkstra算法
- java版UC加密
- POJ 1011 Sticks
- Archlinux to Debian小记
- 采用HttpURLConnection访问服务端
- 理解fork()的一次调用两次执行
- BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题
- HDU 寒冰王座
- 图片上传并预览(IE,火狐浏览器兼容问题)
- Request读取中文数据乱码的原因,以及解决办法
- 备忘:Api查询网址
- [转载]C# 写Windows服务程序
- 解决全屏UI中输入法的问题(一)
- POJ 1703 Find them, Catch them