要理解fork(),首先需要懂得c程序和进程的概念:
c程序组成部分如下:
Text segment,正文段,由CPU执行的及其指令部分,可共享,通常是只读.
Initialized data segment, 初始化数据段,包含程序中需要明确赋初值的变量.
Uninitialized data segment, 非初始化数据段,对应于初始化数据段,又称bss段(block started by symbol,由符号开始的段),程序执行前,由内核初始化为0或空指针.
Stack,栈,存储自动变量和每次函数调用时所需保存的信息,程序递归时回用到栈保存返回地址和调用者的环境信息.
Heap, 堆,通常在堆中进行动态存储分配,位于非初始化数据段和栈之间.
典型的存储器安排如图所示:
至于进程,它主要包含三个元素:
一个可以执行的程序;
和该进程相关联的全部数据(包括变量,内存空间,缓冲区等等);
程序的执行上下文(execution context).
操作系统对进程的管理,典型的情况,是通过进程表完成的.进程表中的每一个表项,记录的是当前操作系统中一个进程的情况.当分给某个进程的 CPU时间已经用完,操作系统将该进程相关的寄存器的值,保存到该进程在进程表中对应的表项里面;把将要接替这个进程占用 CPU的那个进程的上下文,从进程表中读出,并更新相应的寄存器,这个过程称为上下文交换(process context switch).
然后是fork(),由fork创建的新进程称为子进程(child process),操作系统在进程表中相应为子进程建立一个新的表项.fork函数有个特性,”一次调用,二次返回”.它在调用进程(即父进程(parent process))中返回一次,返回值是子进程的ID号;在子进程又返回一次,返回值为0.因此,我们可以通过返回值判断当前进程是父进程还是子进程.
父进程调用fork之前打开的所有描述子在fork返回之后由子进程分享,也就是说,子进程是父进程的副本,它获得父进程的数据空间,堆和栈的拷贝.注意,这里是拷贝,而不是分享,父进程与子进程分享的是正文段.(见前图)
fork()的两个典型用法为:
一个进程创建自身的一个拷贝,这样每个拷贝可以在另外一个拷贝在执行其他任务的同时处理各自的操作,这在网络编程中是很常见的.
一个进程想要执行另外一个程序.因为创建一个新进程的唯一方法是调用fork,所以我们可以用fork创建一个拷贝,然后在子进程中调用exec把自身替换成新的程序.
下面是一个很简单的fork()示例:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
fork();
printf("P1\n");
fork();
printf("P2\n");
}
注意在fork之后,由父进程先执行还是子进程先执行是不确定的,这取决于内核使用的调度算法..
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
pid_t pid;
printf("fork!\n");
pid=fork();
if (pid < 0)
printf("error in fork!");
else if (pid == 0)
printf("i am the child process, my process id is %d\n",getpid());
else
printf("i am the parent process, my process id is %d\n",getpid());
}
输出结果很诡异,为:
fork!
i am the child process, my process id is 4286
i am the parent process, my process id is 4285
为什么这里fork!只输出一次呢?为了对比,可以将printf(“fork!\n”);里面的\n去掉,这时候程序倒是输出两次fork!了..解释如下,其实这与printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里,并没有实际显示到屏幕上.因此fork()后,子进程得到这份拷贝.而当printf()中含有\n时,printf将刷新stdout,因此子进程无法得到这份拷贝,fork!也就理所当然地只输出一次罢了.
- 大小: 14 KB
分享到:
相关推荐
创建新进程:fork函数:fork函数干什么? fork函数与vfork函数的区别在哪里?为何在一个fork的子进程分支中使用_exit函数而不使用exit函数?
linux_fork函数
演示fork函数的效果。也为了挣分。不会fork的可以看看。
fork 函数详解
linux内核 do_fork 函数源代码浅析。 经典讲解!
来自Google的英文原版,翻译。
易懂易用,对于初学者来说是个十分实用的对初学知识的巩固与了解。
本文档内容是我自己写的一个关于fork函数新建进程并对调用流程进行分析的文档。 运行环境是win7安装vmware虚拟机里的linux系统,直接gcc编译得到的执行结果。 看完次文档后即可对fork有一个比较系统的认识。
fork函数[归类].pdf
关于fork函数的介绍,和测试程序,原版fork linux平台
2.fork 函数被调用一次,但返回两次, 两次返回的唯一区别是子进程的返回值是 0, 而父进程的返回值是新子进程的 PID。 3.子进程和父进程继续执行 fork 调用之后的指令。 在上图的存储空间布局中,父子进程只共享正文...
系统调用fork( ), exec系列函数,exit( ), wait( )的功能和实现过程 使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示...
用fork创建子进程; 回答no执行父进程,yes执行父进程并复制进程的操作;在父进程将str3,str4接至str0中,并输出str0 ;在子进程中,将str1,str2接至str0中,并输出str0
在win系统下模拟linux中的fork()函数执行过程与基础通信过程 备注清晰。
原来刚刚开始做Linux下面的多进程编程的时候,对于下面这段代码感到很奇怪: #include #include #include #include #include #include #define LEN 2 void err_exit(char*fmt,…);...
本文档以ppt形式编写,通过例子,学习fork()函数的应用及用法,适合初学者。
对进程初学者来说理解FORK()有帮助, fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0, 这是因为父进程可能存在很多过子进程,所以必须通过这个返回的子进程ID来跟踪子进程,
一些简单的linux下进程管理文件示例,关于fork()函数的,可以作为入门级别的
sourceinlight4
fork函数用于创建子进程,典型的调用一次,返回两次的函数,其中返回子进程的PID和0,其中调用进程返回了子进程的PID,而子进程则返回了0,这是一个比较有意思的函数,但是两个进程的执行顺序是不定的。