一.进程消亡
1.进程退出
(1) 从main函数return退出进程
(2) exit, _exit, _Exit
exit :退出进程会刷新缓冲区(库函数)
_exit, _Exit: 系统调用,退出进程不会刷新缓冲区
void exit(int status); void _exit(int status); void _Exit(int status);
功能:退出一个进程
参数:
status:退出时的状态值(可以传递给父进程)
EXIT_SUCCESS: 0 --->一切正常 退出
EXIT_FAILURE : 1---->当进程发生错误,主动退出
(3) 被动结束:信号结束 (kill)。
2.进程资源回收
僵尸进程:进程已结束,但其资源空间未被其父进程回收。
如何避免僵尸进程:
1. 子进程结束,其父进程使用wait/waitpid回收资源空间
2. 让子进程成为一个孤儿进程,孤儿进程会被系统中的进程收养,由系统进程负责回收。
孤儿进程:父进程先消亡,由该父进程产生的子进程成为孤儿进程,将会被系统进程所收养。( 守护进程一般是孤儿进程)
(1)pid_t wait(int *wstatus);
功能:阻塞回收子进程空间和退出时状态
参数:
wstatus:需要保存的回收的子进程状态值的地址
NULL :不保存状态
返回值:
成功:返回回收到的子进程的ID号
失败:-1
一般用wait(NULL);(不关心子进程的状态)
(2)pid_t waitpid(pid_t pid, int *status, int options);
功能:回收指定进程的资源
和wait功能相似,比wait更灵活
参数:
pid:
<-1 回收指定进程组内的任意子进程 (-100.等待GID=100的进程组中的任意子进程)
-1 回收任意子进程,组内外
0 回收和当前调用waitpid一个组的所有子进程,组内
> 0 回收指定ID的子进程
status :子进程退出时候的状态, 如果不关注退出状态用NULL;
options 选项:
0 表示回收过程会阻塞等待
WNOHANG 表示非阻塞模式回收资源。
返回值: 成功 返回接收资源的子进程pid
失败 -1
设定为非阻塞且没有回收到子进程返回0
waitpid(-1,&status,0) //默认阻塞 ==wait(&status);
非阻塞方式+轮询方式:
waitpid:父进程有自己的任务执行; waitpid(-1, NULL, WNOHANG)。
二.exec函数族(在一个进程中执行外部的一段程序)
原因:exec会将外部程序的指令替换到进程的文本区
(1) int execl(const char *path, const char *arg, ...
/* (char *) NULL */);
path:执行的外部程序对应的路径和名称
arg:执行外部程序需要的参数
(2) int execlp(const char *file, const char *arg, ...
/* (char *) NULL */);
file:要执行的外部程序的名称
arg:执行外部程序需要的参数
(3) int execv(const char *path, char *const argv[]);
path:执行的外部程序对应的路径和名称
argv:执行外部程序需要的参数存放到数组中
(4) int execvp(const char *file, char *const argv[]);
file:要执行的外部程序的名称
argv:执行外部程序需要的参数存放到数组中
l: list : 列表
p: PATH : 环境变量中的路径:env(查看环境变量)
v: vector:容器
#include
#include
int main(int argc, char const *argv[])
{
execl("/bin/ls","ls",NULL);
//execl("./a.out","./a.out",NULL);
//execl("/bin/mv","mv","1.test.c","1.txt",NULL);
char *arg[] = {"ls","-l",NULL};
execv("/bin/ls",arg);
execlp("ls","ls","-l","-a",NULL);
execvp("ls",arg);
return 0;
}
(5)int system(const char *command);
功能:重开一个进程,在子进程中执行外部的一段程序
system("ls -l -a");
(6)char *strtok(char *str, const char *delim);
strtok 函数会在 str 中查找由 delim 中的字符界定的子字符串。它会修改原始字符串,在找到的分隔符位置用空字符 \0 替换,然后返回指向被分割出的子字符串的指针。
第一次调用 strtok 时,需要传入要分割的完整字符串作为 str 参数。后续调用为了继续在原字符串中进行分割操作,需要将 str 参数设为 NULL , strtok 会记住上次分割的位置并继续查找下一个子字符串。