点击蓝字 关注我们
linux 基础,你掌握了几个?今天,我邀请了蓝桥云课合作作者——跑不了的你,给大家整理了 linux 基础——进程的退出及资源回收~希望对大家有帮助!(记得注意文末教育优惠哦~)
进程的退出
returen 和 exit,return 只是函数的返回,而 exit 却是进程的结束。
void exit(int status);
-
#include <stdlib.h>
-
void exit(int status);
-
功能:终止进程
-
参数:
-
status:退出状态码。status&
0377的值给父进程。
-
返回值:
-
永远不返回。
代码示例
-
#include <stdio.h>
-
#include <stdlib.h>
-
int main(void){
-
getchar();
-
exit(
-1);
-
}
执行结果
注册进程结束调用函数
在进程结束前,可以注册一些函数给进程,在进程结束时会自动调用这些被注册的函数。
on_exit(3)
-
#include <stdlib.h>
-
-
-
int on_exit(void (*function)(int , void *), void *arg);
-
-
-
功能:注册一个函数给进程,在进程终止的时候调用该函数
-
参数:
-
function:指定退出函数的名字
-
void (*function)(
int ,
void *)
-
arg:指定退出函数的第二个参数
-
返回值:
-
0 成功
-
非
0 错误
代码示例(on_exit)
-
#include <stdio.h>
-
#include <stdlib.h>
-
void doit(int n,void *arg){
-
printf(
"n=%d\targ:%s\n",\
-
n,(
char *)arg);
-
return;
-
}
-
-
-
int main(void){
-
//向进程注册退出函数
-
on_exit(doit,
"beijing");
-
getchar();
-
exit(
3);
-
}
执行结果
atexit
atexit(3)
-
#include <stdlib.h>
-
int atexit(void (*function)(void));
-
功能:注册一个函数给进程,在进程终止的时候调用该函数
-
参数:
-
function:指定了要注册的函数的名字
-
返回值:
-
0 成功
-
非
0 错误
代码示例(atexit)
-
#include <stdio.h>
-
#include <stdlib.h>
-
-
-
//注册给进程的退出函数
-
void doit(void){
-
printf(
"hahha....\n");
-
return;
-
}
-
-
-
int main(void){
-
//向进程注册一个退出处理函数
-
atexit(doit);
-
getchar();
-
return
0;
-
}
执行结果
进程资源的回收
在进程退出后,父进程会回收子进程的资源。
使用 wait(2)、waitpid(2) 系统调用回收子进程的资源。
如果父进程早于子进程结束,那么父进程的子进程的父亲就改变成为 init 进程,这种进程被成为孤儿进程。
代码示例
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <stdlib.h>
-
-
-
int main(void){
-
pid_t pid;
-
//创建子进程
-
pid=fork();
-
if(pid==
-1){
-
perror(
"fork");
-
return
1;
-
}
-
if(pid==
0){
//子进程的代码
-
sleep(
5);
-
printf(
"child...\n");
-
//getchar();
-
exit(
0);
-
}
else{
//父进程的代码
-
printf(
"parent...\n");
-
exit(
0);
-
}
-
return
0;
-
}
执行结果
wait 回收进程资源
-
#include <sys/types.h>
-
#include <sys/wait.h>
-
pid_t wait(int *status);
-
功能:等待进程改变状态。
-
参数:
-
status:退出状态码的地址。子进程的退出状态存放在这块地址空间里。可以使用一些宏检测退出原因。
-
WIFEXITED(status) 如果正常死亡,返回真
-
WEXITSTATUS(status) 返回子进程的退出状态和
0377的与,那个值。
-
WIFSIGNALED(status) 如果子进程被信号终止,返回真
-
WTERMSIG(status) 检测被几号信号终止。只有上个宏为真的时候,才使用。
-
-
-
返回值:
-
-1 错误
-
返回终止的子进程的pid
代码示例
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/wait.h>
-
int main(void){
-
pid_t pid;
-
int s;
-
//创建子进程
-
pid=fork();
-
if(pid==
-1){
-
perror(
"fork");
-
return
1;
-
}
-
if(pid==
0){
-
printf(
"child pid=%d\n",\
-
getpid());
-
//sleep(5);
-
getchar();
-
exit(
-1);
-
}
else{
-
//等待子进程的结束
-
wait(&s);
-
if(
WIFEXITED(s)){
-
//子进程正常终止
-
printf(
"status:%d\n",
WEXITSTATUS(s));
-
}
-
//检测子进程是否被信号终止
-
if(
WIFSIGNALED(s)){
-
//输出终止子进程的信号编号
-
printf(
"signum :%d\n",\
-
WTERMSIG(s));
-
}
-
printf(
"parent...\n");
-
}
-
return
0;
-
}
执行结果
waitpid
pid_t waitpid(pid_t pid,int *status,int options);
-
功能:等待进程改变状态。
-
参数:
-
pid:
-
< -1: pid取绝对值,如果子进程的组id等于这个绝对值,那么这个子进程就被等待。
-
-1:等待任意子进程
-
0:等待和当前进程有同一个组id的子进程
-
> 0 等待子进程的pid是pid参数的子进程。
-
status:同wait(2)参数的使用
-
options:
-
WNOHANG:非阻塞回收。
-
0 阻塞回收
-
返回值:
-
-1 错误
-
0 没有子进程退出
-
回收的子进程的pid
代码示例
waitpid.c
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/wait.h>
-
int main(void){
-
pid_t pid;
-
int s;
-
//创建子进程
-
pid=fork();
-
if(pid==
-1){
-
perror(
"fork");
-
return
1;
-
}
-
if(pid==
0){
-
printf(
"child pid=%d\n",\
-
getpid());
-
//sleep(5);
-
getchar();
-
exit(
-1);
-
}
else{
-
//非阻塞等待子进程的结束
-
waitpid(
-1,&s,WNOHANG);
-
if(
WIFEXITED(s)){
-
//子进程正常终止
-
printf(
"status:%d\n",
WEXITSTATUS(s));
-
}
-
//检测子进程是否被信号终止
-
if(
WIFSIGNALED(s)){
-
//输出终止子进程的信号编号
-
printf(
"signum :%d\n",\
-
WTERMSIG(s));
-
}
-
printf(
"parent...\n");
-
}
-
return
0;
-
}
执行结果
给指定进程发送信号(kill)
kill -[信号编号] [进程的pid]
僵尸进程
子进程已经终止,但是父进程还没有回收子进程的资源,这时候的子进程处于僵尸状态,成为僵尸进程。
代码示例
zombile.c
-
#include <stdio.h>
-
#include <sys/types.h>
-
#include <sys/wait.h>
-
#include <unistd.h>
-
#include <stdlib.h>
-
int main(void){
-
pid_t pid;
-
pid=fork();
-
if(pid==
-1){
-
perror(
"fork");
-
return
1;
-
}
-
if(pid==
0){
-
exit(
0);
-
}
else{
-
sleep(
20);
-
wait(
NULL);
-
}
-
return
0;
-
}
在进程的虚拟地址空间加载新的映像
在子进程的虚拟地址空间加载新的影像,需要使用系统提供的一个家族的函数。
execl(3)
-
#include <unistd.h>
-
extern
char **environ;
-
int execl(const char *path, const char *arg, ...);
-
int execlp(const char *file, const char *arg, ...);
-
int execle(const char *path, const char *arg,\
-
..., char * const envp[]);
-
int execv(const char *path, char *const argv[]);
-
int execvp(const char *file, char *const argv[]);
-
int execvpe(const char *file, char *const argv[],
-
char *
const envp[]);
execve(2)
-
#include <unistd.h>
-
int execve(const char *filename, char *const argv[],\
-
char *
const envp[]);
-
相同的exec
-
l list
-
v vector
-
p PATH
-
e 环境变量
-
返回值:
-
成功调用永远不返回
-
-1 错误 errno被设置
代码示例
exec.c
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <sys/types.h>
-
#include <sys/wait.h>
-
char *
const ps_argv[]={
"ps",
"-o",
"pid,ppid,pgrp,comm",
NULL};
-
-
-
int main(void){
-
pid_t pid;
-
-
//创建子进程
-
pid=fork();
-
if(pid ==
-1){
-
perror(
"fork");
-
return
1;
-
}
-
if(pid==
0){
-
//加载新映像
-
//execl("/bin/ps","ps","-o",\
-
"pid,ppid,pgrp,comm",NULL);
-
-
//execlp("ps","ps","-o",\
-
"pid,ppid,pgrp,comm",NULL);
-
execvp(
"ps",ps_argv);
-
}
else{
-
wait(
NULL);
-
}
-
return
0;
-
}
执行结果
使用 system 启动新的可执行程序
-
#include <stdlib.h>
-
int system(const char *command);
-
功能:执行一个shell命令
-
参数:
-
command:可执行命令
-
返回值:
-
-1 错误
-
返回command的退出状态码。
代码示例
system.c
-
#include <stdio.h>
-
#include <sys/types.h>
-
#include <sys/wait.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
-
-
int main(void){
-
pid_t pid;
-
pid=fork();
-
if(pid==
-1){
-
return
1;
-
}
-
if(pid==
0){
-
execl(
"./myt",
"myt",
NULL);
-
//system("myt");
-
exit(
0);
-
}
else{
-
wait(
NULL);
-
}
-
return
0;
-
}
执行结果
另外,作者在蓝桥云课上线了《Linux 操作系统原理剖析》,以 Linux 操作系统为基础对操作系统实现原理进行深入讲解,分析操作系统中的内存管理、进程管理、文件系统管理、设备管理、网络管理等几大子模块的实现原理。
如果想学此门课程,欢迎扫文末二维码优惠学!除此之外,大家还可选择教育优惠哦~
号外!号外!
蓝桥云课专属教育优惠重磅上线啦!
仅需完成学生认证,
即享 5 折学生优惠券!
▼扫码完成学生认证▼
▲课程优惠学▲
戳戳“阅读原文”直达课程页面!
转载:https://blog.csdn.net/MOY37RQW1JarN33BgZk/article/details/125288813