嵌入式开发学习日志(linux系统编程--进程(2))Day28
一、进程的退出
僵尸进程和孤儿进程
僵尸进程:进程执行结束但空间未被回收变成僵尸进程;
孤儿进程:父进程先结束,先消亡;
二、进程结束的函数
1、exit(1);
void exit(int status);
【int status】退出状态,终止的进程会通知父进程,自己使如何终止的。如果是正常结束(终止),则由exit传入的参数。如果是异常终止,则有内核通知异常终止原因的状态。任何情况下,父进程都能使用wait,waitpid获得这个状态,以及资源的回收。(包括文件的关闭、堆释放、缓冲区清理)
功能:
让进程退出,并刷新缓存区
参数:
status:进程退出的状态
返回值:
缺省
8个bite位
EXIT_SUCCESS 0————正常退出
EXIT_FAILURE 1 ————错误退出/
2、 _exit 系统调用
void _exit(int status);
功能:
让进程退出,不刷新缓存区
参数:
status:进程退出状态
返回值:
缺省
3、atexit
int atexit(void (*function)(void));
void (*function)(void)——回调函数
功能:
注册进程退出前执行的函数
参数:
function:函数指针
指向void返回值void参数的函数指针
返回值:
成功返回0
失败返回非0
当程序调用exit或者由main函数执行return时,所有用atexit
注册的退出函数,将会由注册时顺序倒序被调用
注意:
①和exit()配合使用。
_exit()不可以;
②当程序执行到exit()时候,若有注册函数,先执行注册函数,在执行exit();
③由于此处的回调函数没有参数和返回值,所以针对变量时,必须为全局变量;
三、进程空间的回收
在Linux系统中,只能由父进程回收子进程,不能用子进程回收父进程;
1、回收函数wait/waitpid
pid_t wait(int *wstatus);
功能:该函数可以阻塞等待任意子进程退出
并回收该进程的状态。
一般用于父进程回收子进程状态。
参数:
【int *wstatus】:常用的四个宏
1、【WIFEXITED(wstatus)】
2、【WEXITSTATUS(wstatus)】
3、【WIFSIGNALED(wstatus)】
4、【 WTERMSIG(wstatus)】
注意:①若子进程未结束,则该函数会进入阻塞状态等到进程结束;
②一次回收一个,若父进程有很多子进程,调用wait函数,随机回收一个
③如果一个子进程终止,正在等待的父进程则获得终止状态,获得子进程的状态后,立刻返回。
④如果没有子进程,则立即出错退出。
2、waitpid
pid_t waitpid(pid_t pid, int *status, int options);
参数:
【pid_t pid】:需要回收的子进程的pid号;
【int *status】:子进程退出时候的状态,
如果不关注退出状态用NULL;
【int options】:0 表示回收过程会阻塞等待
WNOHANG 表示非阻塞模式回收资源。(子进程未退出,稍后在试)
返回值:
成功 返回回收资源的子进程pid
如果返回值为0时,则标明为非阻塞,回收失败;
错误时,返回值为-1;
注意:非阻塞回收时,CPU占用率比较高;
3、exec族
①用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),
②子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的
③用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建
④新进程,所以调用exec前后该进程的id并未改变。
(1)execl
形式:
int execl(const char *path, const char *arg, ... /* (char *) NULL */);
参数
【const char *path】:需要执行的程序位置;(路径加文件名)
【const char *arg ,...】:命令或程序本身,不需要带位置;
需要操作的内容,单个传参,但是不能用空格
【/* (char *) NULL */】:末尾写入NULL,证明参数已经传完了;
(2)execlp(只会走PATH路径下的文件)
形式:
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
【const char *file】:
【const char *arg ,...】:命令或程序本身,不需要带位置;
需要操作的内容,单个传参,但是不能用空格
【/* (char *) NULL */】:末尾写入NULL,证明参数已经传完了;
(3)execv
形式:
int execv(const char *path, char *const argv[]);
【const char *path】:需要执行的程序位置;(路径加文件名)
【char *const argv[]】:指针数组
(4)execvp
形式:
int execvp(const char *file, char *const argv[]);
【const char *file】:
【 char *const argv[]】:指针数组