1、僵尸进程
- 子进程结束但是没有完全释放内存(在内核中的task_struct没有释放),该进程就成为僵尸进程。
- 当僵尸进程的父进程结束后就会被init进程领养,最终被回收。
- 避免僵尸进程
- 让僵尸进程的父进程来回收,父进程每隔一段时间来查询子进程是否结束并回收,调用wait()或者waitpid()通知内核释放僵尸进程。
- 采用信号SIGCHLD通知处理,并在信号处理程序中调用wait函数
- 让僵尸进程成为孤儿进程,由init进程回收。
2、守护进程
- 守护进程(daemon)是生存期长的一种进程。它们常常在系统引导装入时起动,在系统关闭时终止。
- 所有守护进程都以超级用户(用户ID为0)的优先权运行。
- 守护进程没有控制终端
- 守护进程的父进程都init进程
3、孤儿进程
父进程结束,子进程就成为孤儿进程,会由1号进程(init进程)领养。
4、wait函数
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int * status);
返回:成功返回子进程ID,出错返回-1
功能:等待子进程退出并回收,防止孤儿进程产生
pid_t waitpid(pid_t pid,int* status,int options);
返回:成功返回子进程ID,出错返回-1
功能:wait函数的非阻塞版本
4.1、wait和waitpid函数区别
- 在一个子进程终止前,wait使其调用者阻塞。
- waitpid有一选择项,可使调用者不阻塞。
- waitpid等待一个指定的子进程,而wait等待所有的子进程,返回任一终止子进程的状态。
4.2、status参数
- 为空时,代表任意状态结束的子进程,若不为空,则代表指定状态结束的子进程。
4.3、检查wait和waitpid函数返回终止状态的宏
4.4、options参数
- WAOHANG
- 若由pid指定的子进程没有退出则立即返回,则waitpid不阻塞,此时其返回值为0.
- WUNTRACED
- 若某实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态。
4.5、 waitpid函数的pid参数
- pid=-1
- 等待任一子进程,功能与wait等效。
- pid>0
- 等待其进程ID与pid相等的子进程。
- pid==0
- 等待其组ID等于调用进程的组ID的任一子进程
- pid<-1
- 等待其组ID等于pid的绝对值的任一子进程。
5、exec函数
- 在用fork函数创建子里程后,子进程往往要调用一种exec函数以执行另一个程序
- 当进程调用一种exec函数时,该进程完全由新程序代换,替换原有进程的正文,而程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆、栈段。
#include<unistd.h>
int execl(const char * pathname,const char *arg0……/*(cahr*)0*/);
int execv(const char * pathname,const char *argv[]);
int execle(const char * pathname,const char *arg0……/*(cahr*)0*/,const char *argv[]);
int execve(const char * pathname,const char *argv[],char *const envp[]);
int execlp(const char * pathname,const char *arg0……/*(cahr*)0*/);
int execvp(const char * pathname,const char *argv[]);
返回:出错返回-1,成功则不返回
exec系列函数的注意点
- execve函数为系统调用,其余为库函数。执行execve函数后面的代码不执行。
- execlp和excevp函数中的pathname,相对和绝对路径均可使用,其它四个函数中的pathname只能使用绝对路径。相对路径一定要在进程环境表对就把PATH中。
- argv参数为新程序执行main函数中传递的argv参数,最后一个元素为NULL。
envp为进程的环境表。
六个函数都是以“exec”四个字母开关的,后面的字母表示了其用法上的区别:
- 带有字母“I”的函数,表明后面的参数列表是要传递给程序的参数列表,参数列表的第一个参数必须要执行程序,最后一个参数必须是NULL。
- 带有字母“P”的函数,第一个参数可以是相对路径或程序名,如果无法立即找到要执行的程序,那么就在环境变量PATH指定的路径中搜索。其它函数的第一个参数则必须是绝对路径。
- 带有字母“V”的函数,表明程序的参数列表通过一个字符串数组来传递。这个数组和最后传递给程序的main函数的字符串数组argv完全一样。第一个参数必须是程序名,最后一个参数也必须是NULL。
- 带有字母“e”的函数,用户可以自己设置程序接收一个设置环境变量的数组。
6.system函数
#include<stdio.h>
int system(const char * command);
返回:成功返回执行命令的状态,出错返回-1
功能:简化exec函数的使用
- system函数内部构建一个子进程,由子进程调用exec函数。
- 等同于/bin/bash -c”cmd”或者 exec(“bash”,”-c”,”cmd”);
7、进程状态切换