fork()&&进程的创建与终止--多进程编程
来源:互联网 发布:中国反倾销数据统计 编辑:程序博客网 时间:2024/06/05 21:51
(1)进程的创建和执行。
许多操作系统都提供的是产生进程的机制,也就是首先在新的地址空间里创建进程、读入可执行文件,
最后再开始执行。Linux 中进程的创建很特别,它把上述步骤分解到两个单独的函数中取执行:fork()
和 exec 函数族。首先,fork()通过复制当前进程创建一个子进程,子进程与父进程的区别仅仅在于不
同的 PID、PPID 和某些资源及统计量。exec 函数族负责读取可执行文件并将其载入地址空间开始运行。
要注意的是,Linux 中的 fork()使用的是写时复制(copy on write)的技术,也就是内核在创建进
程时,其资源并没有立即被复制过来,而是被推迟到需要写入数据的时候才发生。在此之前只是以只读的
方式共享父进程的资源。写时复制技术可以使 Linux 拥有快速执行的能力,因此这个优化是非常重要的。
(2)进程的终止。
进程终止也需要做很多烦琐的收尾工作,系统必须保证进程所占用的资源回收,并通知父进程。Linux
首先把终止的进程设置为僵死状态。这个时候,进程已经无法运行。它的存在只为父进程提供信息。父进
程在某个时间调用 wait 函数族,回收子进程的退出状态,随后子进程占用的所有资源被释放。
1.fork()
在 Linux 中创建一个新进程的唯一方法是使用 fork()函数。fork()函数是 Linux 中一个非常重要的函数,和读者以往遇到的函数有一些区别,因为它看起来执行一次却返回两个值。一个函数真的能同时返回两个
值吗?希望读者能认真地学习下面的内容。
(1)fork()函数说明。
fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。使用
fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程上
下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号处理函数、进程优先级、进程组号、当前
工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等。
这样的得到的子进程是独立于父进程的,具有良好的并行性,但是二者之间要使用专门的通讯机制。比如:pipe
,共享内存等。另外通过fork创建子进程,需要把上面的全部复制一下是开销很大的,但是由于现在linux采用采用了
一种写时复制的的技术,减少开销。其实开始并不会真的产生两个复制,因为这个时候大量数据是一样的,子进程仅仅
是以读的形式共享父进程的资源。写时复制在推迟真正的数据复制,如果后来真的要写入数据,这个时候意味着父进程和
子进程的数据不一致了,才产生复制的动作。
因为子进程几乎是父进程的完全复制,所以父子两个进程会运行同一个程序。因此需要用一种方式来
区分它们,并使它们照此运行,否则,这两个进程只能做相同的事。
父子进程一个很重要的区别是:fork()的返回值不同。父进程中的返回值是子进程的进程号,而子进
程中返回 0。可以通过返回值来判定该进程是父进程还是子进程。
注意:子进程没有执行 fork()函数,而是从 fork()函数调用的下一条语句开始执行。
(2)fork()函数语法。
表 3.1 列出了 fork()函数的语法要点。
表 3.1 fork()函数语法要点
所需头文件 #include <sys/types.h> /* 提供类型 pid_t 的定义 */
#include <unistd.h>
函数原型 pid_t fork(void);
函数返回值
0:子进程
子进程 PID(大于 0 的整数):父进程
1:出错
fork()函数的简单的示例程序如下。
int main(void) { pid_t ret; /*调用 fork()函数*/ ret = fork(); /*通过 ret 的值来判断 fork()函数的返回情况,首先进行出错处理*/ if(ret == -1) { perror("fork error"); return -1; } else if (ret == 0) /*返回值为 0 代表子进程*/ { printf("In child process!! ret is %d, My PID is %d\n", ret, getpid()); } else /*返回值大于 0 代表父进程*/ { printf("In parent process!! ret is %d, My PID is %d\n", ret, getpid()); } return 0; }
编译并执行程序,结果如下。
$ gcc fork.c –o fork -Wall $./fork In parent process!! ret is 3876, My PID is 3875 In child process!! ret is 0, My PID is 3876
从该示例中可以看出,使用 fork()函数新建了一个子进程,其中的父进程返回子进程的进程号,而子
进程的返回值为 0。
2.vfork()这个函数和fork()的区别是创建的子进程和父进程共享地址空间,如果说子进程完全运行在父进程的地址空间之上,如果子进程修改了某个变量,就会影响到父进程。
但是需要注意的一点事,用vfork()创建子进程必须显示的调用exit()来结束,否则子进程不会结束。而fork()不存在这种情况。
- fork()&&进程的创建与终止--多进程编程
- 从系统调用fork,到进程的创建与终止
- Windows核心编程(四)进程的创建与终止
- OS之 进程的创建与终止
- fork与vfork创建进程的区别
- 进程基础-进程的创建、管理与调度、终止
- fork创建多进程
- 创建守护进程fork一次与fork两次的区别
- VC进程的创建、终止
- 【C/C++】多进程:子进程的创建fork()
- 进程的基本操作,fork(),创建多进程。
- 进程的创建: fork/execve
- 【Linux】进程的创建fork()
- 进程创建fork与vfork,孤儿进程,僵尸进程
- CreateProcess TerminateProcess 创建与终止进程 demo
- 进程创建和进程终止
- 多进程编程中fork
- C进程创建fork与vfork的区别
- JPEGsnoop算法研究以及制作可以通过检测的原图
- muduo日志2
- 结构体指针
- 11. Firefox如何调试js脚本:
- Nagios 监控mysql服务器详细实现过程
- fork()&&进程的创建与终止--多进程编程
- 利用ajaxFileupload实现表单和图片同时上传
- muduo日志3
- MySQL技术内幕-InnoDB存储引擎-读书笔记(一)
- sublime text2小技巧
- 12.The APR based Apache Tomcat Native library which allows optimal performance
- Java设计模式 装饰类
- VMware Workstation文件共享
- block里面的self要使用弱引用,否则会无法释放内存