进程创建
进程创建被定义为通过父进程创建子进程的过程。
fork函数
函数原型:pid_t fork(void);
特点:
1.fork函数调用一次,返回两次两次返回值得区别分别是子进程当中的返回值为0,父进程当中的返回值为新建子进程的ID(将ID返回给父进程的原因是没有函数可以使父进程得到子进程的ID,这样会便于管理);
2.子进程被创建出来后,子进程是父进程的副本(子进程获得父进程数据空间,堆,栈的副本<一定注意是副本>);
3.父进程和子进程只共享正文段(.text);
4.由于fork之后经常跟随者exec(程序加载函数),所以现在很多操作系统的实现并不执行一个父进程的副本,而是使用了写时拷贝(这些区域由父子进程所共享,而且内核将这些区域的访问权限设定为只读权限,如果父进程和子进程中的任意一个区域试图被修改,则内核会为修改区域产生一个副本)。
5.fork之后父进程和子进程的执行顺序是随机的,取决于内核所使用的调度算法。
6.关于文件共享,这部分内容和文件描述符有关大家可以看看下面这篇博客:http://blog.csdn.net/bit_clearoff/article/details/54565044
7.父进程和子进程的区别:
- fork的返回值不同
- 进程ID,父进程ID不同
- 子进程不继承父进程设置的文件锁
- 子进程未处理的闹钟被清楚
- 子进程未处理的信号集,被设置为空集
函数vfork
vfork函数也是创建进程,但是与fork函数不相同的是:
1.vfork创建一个新进程,而新进程的目的是exec一个新程序;
2.vfork并不将父进程的地址空间完全复制到子进程中;
3.子进程在调用exec函数或者exit函数之前,子进程在父进程的空间中运行;
4.vfork函数保证子进程先运行,在它调用exec或exit函数之后父进程才会被恢复运行。
进程终止
进程有五种正常终止方式和三种异常终止方式,他们分别是:
五种正常终止方式
1.在main函数内执行return 语句。它等效于调用exit;
2.调用exit函数,exit函数由C库定义,其操作包含调用各种终止处理程序,关闭所有标准I/O流等。详细的大家可以看看下面这篇博客:
http://blog.csdn.net/bit_clearoff/article/details/54425362
3.调用_exit函数,exit函数和_exit函数的不用地方就是它为进程提供了一种无需终止运行终止处理程序或信号处理程序而终止的办法。
4.进程的最后一个线程在其启动例程中执行return语句.(这个现在大家先了解即可,关于线程的知识后面会详细分析)
5.进程的最后一个线程调用pthread_exit函数。
三种异常终止方式
1.调用absort。
2.当进程接收到某些信号时。
3.最后一个线程对“取消请求作出响应”。
不管进程以上面的何种方式进行终止,都会执行内核中的同一段代码,这段代码为相应的进程关闭所有打开的描述符,释放进程所拥有的地址空间。
另外,对任意一种终止情形,父进程都希望得到所终止的子进程的相关退出信息,对于三个终止函数,都采用了输出型参数status得到子进程的退出状态和信息;在异常情况中,内核产生一个指示其异常终止原因的终止状态,另外,父进程可以用wait函数和waitpid函数取得子进程的终止状态。
上面提到的都是子进程先被终止,然后父进程回收子进程的相关状态,这时被终止的子进程被称为僵死进程(注意父进程此时还没有被终止);