一、进程的销毁
-
1.释放资源
-
2.记账信息
-
3.将进程状态设置设置成僵尸状态
-
4.转存储调度
二、进程终止的方法
1、正常退出
-
1. void _exit ( int status)
-
status定义了进程终止状态,父进程通过wait来获取该值
-
退出码为0正常退出,非0异常退出(8-16位为退出码,退出码在0-255之间)
-
echo $? //上一条指令的退出码
-
-
2. void exit ( int status )
-
exit( ) 最终也会调用_exit( )函数,调用前会刷新stdio流缓冲区
-
-
3.return退出
-
执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值作为exit的参数
-
exit和_exit的区别
-
exit是函数
-
_exit是系统的API接口
注册退出处理程序
-
int atexit(void(*func)(void));
-
#include<stdlib.h>
-
函数atexit()将func加到一个函数列表中,进程终止时会调用该函数列表的所有函数。
-
-
void func(void);
-
atexit()在调用出错的时候返回非0值(不一定是-1);
-
可以注册多个退出处理程序,当程序调用exit()时,这些函数的执行顺序和注册表顺序相反。
-
2、异常退出
-
1. ctrl + c
-
2. assert ( )
-
3. abort ( )
-
4. 信号终止
-
5. 发生了软件事件,例如:定时器到期,进程执行的CPU事件超出限制,或者该进程的某个子进程退出。
-
6. 硬件发生异常
三、进程等待
-
子进程退出父进程不去回收,则可能造成僵尸进程的问题,无法杀掉,且会造成内存泄漏
-
通过父进程可wait()函数等待并回收子进程资源、获取子进程退出信息
回收僵尸子进程
系统调用wait( )等待调用进程的任一子进程死亡后,同时在参数status指向的缓冲区中返回该子进程的终止状态。
wait()
-
pid_t wait ( int * status )
-
作用: 等待子进程结束,回收僵尸子进程
-
头文件:#include<sys/types.h>
-
#include<sys/wait.h>
-
返回值:成功返回被回收的子进程ID,失败返回-1
系统调用wait()执行如下动作:
-
如果调用进程并无之前未被等待的子进程终止,调用将一直阻塞,直至某个子进程终止。如果调用时已有子进程终止,wait()即刻返回,并且释放资源、获取子进程退出信息。
-
如果status非空,那么关于子进程如何终止的信息则会通过status指向的整型变量返回
-
内核将会为父进程下所有子进程的运行总量追加进程CPU时间以及资源使用数据。
-
将终止子进程的PID作为wait()的结果返回。
waitpid()
-
pid_t waitpid(pid_t pid , int * status ,int options);
-
参数:
-
pid:pid=-1等待任一子进程,与wait等效
-
-
pid>0,等待当前进程ID为pid的子进程
pid=0等待本组进程任一一个子进程死亡
- status:WIFEXITED(status) :如果正常退出,返回真
WEXITSTATUS(status) :返回子进程的退出码
-
options:是一个位掩码,可包含0个或多个标志,一般写0(阻塞)
WNOHANG进程没有结束返回0,不予等待,正常结束则返回子进程ID(非阻塞)
正常退出执行结果:
10秒以内在另一个终端下执行以下命令杀死子进程3132
此时子进程非正常死亡,因此不执行 if(WIFEXITED)下的语句
四、进程替换
用fork创建子进程后执行的是和父进程相同的程序,子进程往往调用exec函数以执行另一个程序,当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动历程开始执行,调用exec函数并不创建新进程,调用exec前后改进程的id并未改变。
exec
v:vector 参数采用数组
l:list 参数采用列表
p:path 表示自动搜索环境变量PATH
e:envir 表示自己维护环境变量
execl(const char* path,const char* arg,...);
execlp(const char* file,const char* arg);
execle(const char* path,const char* arg,... , char* const envp[ ]);
execv(const char* path,char* const argv[ ]);
execvp(const char* file,char* const argv[ ]);
execve(const char* path,char* const argv[],... , char* const envp[ ]);
-
如果调用成功则加载新的程序从启动代码开始执行,不再返回
-
调用失败则返回-1
-
exec函数只有失败的返回值没有成功的返回值