linux 基础,你掌握了几个?

打印 上一主题 下一主题

主题 777|帖子 777|积分 2331


点击蓝字 关注我们

linux 基础,你掌握了几个?今天,我邀请了蓝桥云课合作作者——跑不了的你,给大家整理了 linux 基础——进程的退出及资源回收~希望对大家有帮助!(记得注意文末教育优惠哦~)


进程的退出

returen 和 exit,return 只是函数的返回,而 exit 却是进程的结束。

void exit(int status);
  1. #include <stdlib.h>
  2. void exit(int status);
  3. 功能:终止进程
  4. 参数:
  5. status:退出状态码。status&0377的值给父进程。
  6. 返回值:
  7. 永远不返回。
复制代码
代码示例



  • test.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(void){
  4.   getchar();
  5.   exit(-1);
  6. }
复制代码


  • 执行结果


注册进程结束调用函数

在进程结束前,可以注册一些函数给进程,在进程结束时会自动调用这些被注册的函数。
on_exit(3)
  1. #include <stdlib.h>
  2. int on_exit(void (*function)(int , void *), void *arg);
  3. 功能:注册一个函数给进程,在进程终止的时候调用该函数
  4. 参数:
  5. function:指定退出函数的名字
  6. void (*function)(int , void *)
  7. arg:指定退出函数的第二个参数
  8. 返回值:
  9. 0    成功
  10. 非0   错误
复制代码
代码示例(on_exit)



  • on_exit.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void doit(int n,void *arg){
  4.   printf("n=%d\targ:%s\n",\
  5.     n,(char *)arg);
  6.   return;
  7. }
  8. int main(void){
  9.   //向进程注册退出函数
  10.   on_exit(doit,"beijing");
  11.   getchar();
  12.   exit(3);
  13. }
复制代码


  • 执行结果


atexit

atexit(3)
  1. #include <stdlib.h>
  2. int atexit(void (*function)(void));
  3. 功能:注册一个函数给进程,在进程终止的时候调用该函数
  4. 参数:
  5. function:指定了要注册的函数的名字
  6. 返回值:
  7. 0    成功
  8. 非0   错误
复制代码
代码示例(atexit)



  • atexit.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. //注册给进程的退出函数
  4. void doit(void){
  5.   printf("hahha....\n");
  6.   return;
  7. }
  8. int main(void){
  9.   //向进程注册一个退出处理函数
  10.   atexit(doit);
  11.   getchar();
  12.   return 0;
  13. }
复制代码


  • 执行结果

进程资源的回收

在进程退出后,父进程会回收子进程的资源。

使用 wait(2)、waitpid(2) 系统调用回收子进程的资源。

如果父进程早于子进程结束,那么父进程的子进程的父亲就改变成为 init 进程,这种进程被成为孤儿进程。



代码示例



  • lonely.c
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. int main(void){
  5.   pid_t pid;
  6.   //创建子进程
  7.   pid=fork();
  8.   if(pid==-1){
  9.     perror("fork");
  10.     return 1;
  11.   }
  12.   if(pid==0){//子进程的代码
  13.     sleep(5);
  14.     printf("child...\n");
  15.     //getchar();
  16.     exit(0);
  17.   }else{//父进程的代码
  18.     printf("parent...\n");
  19.     exit(0);
  20.   }
  21.   return 0;
  22. }
复制代码


  • 执行结果


wait 回收进程资源

  1. #include <sys/types.h>
  2. #include <sys/wait.h>
  3. pid_t wait(int *status);
  4. 功能:等待进程改变状态。
  5. 参数:
  6. status:退出状态码的地址。子进程的退出状态存放在这块地址空间里。可以使用一些宏检测退出原因。
  7. WIFEXITED(status)  如果正常死亡,返回真
  8. WEXITSTATUS(status)  返回子进程的退出状态和0377的与,那个值。
  9. WIFSIGNALED(status) 如果子进程被信号终止,返回真
  10. WTERMSIG(status)  检测被几号信号终止。只有上个宏为真的时候,才使用。
  11. 返回值:
  12. -1   错误
  13. 返回终止的子进程的pid
复制代码



代码示例



  • wait.c

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6. int main(void){
  7.   pid_t pid;
  8.   int s;
  9.   //创建子进程
  10.   pid=fork();
  11.   if(pid==-1){
  12.     perror("fork");
  13.     return 1;
  14.   }
  15.   if(pid==0){
  16.     printf("child pid=%d\n",\
  17.       getpid());
  18.     //sleep(5);
  19.     getchar();
  20.     exit(-1);
  21.   }else{
  22.     //等待子进程的结束
  23.     wait(&s);
  24.     if(WIFEXITED(s)){
  25.       //子进程正常终止
  26.       printf("status:%d\n",          WEXITSTATUS(s));
  27.     }
  28.     //检测子进程是否被信号终止
  29.     if(WIFSIGNALED(s)){
  30.       //输出终止子进程的信号编号
  31.       printf("signum :%d\n",\
  32.         WTERMSIG(s));
  33.     }
  34.     printf("parent...\n");
  35.   }
  36.   return 0;
  37. }
复制代码


  • 执行结果

waitpid

pid_t waitpid(pid_t pid,int *status,int options);
  1. 功能:等待进程改变状态。
  2. 参数:
  3. pid:
  4. < -1: pid取绝对值,如果子进程的组id等于这个绝对值,那么这个子进程就被等待。
  5. -1:等待任意子进程
  6. 0:等待和当前进程有同一个组id的子进程
  7. > 0   等待子进程的pid是pid参数的子进程。
  8. status:同wait(2)参数的使用
  9. options:
  10. WNOHANG:非阻塞回收。
  11. 0    阻塞回收
  12. 返回值:
  13. -1   错误  
  14. 0   没有子进程退出
  15. 回收的子进程的pid
复制代码
代码示例


  • waitpid.c
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6. int main(void){
  7.   pid_t pid;
  8.   int s;
  9.   //创建子进程
  10.   pid=fork();
  11.   if(pid==-1){
  12.     perror("fork");
  13.     return 1;
  14.   }
  15.   if(pid==0){
  16.     printf("child pid=%d\n",\
  17.       getpid());
  18.     //sleep(5);
  19.     getchar();
  20.     exit(-1);
  21.   }else{
  22.     //非阻塞等待子进程的结束
  23.     waitpid(-1,&s,WNOHANG);
  24.     if(WIFEXITED(s)){
  25.       //子进程正常终止
  26.       printf("status:%d\n",          WEXITSTATUS(s));
  27.     }
  28.     //检测子进程是否被信号终止
  29.     if(WIFSIGNALED(s)){
  30.       //输出终止子进程的信号编号
  31.       printf("signum :%d\n",\
  32.         WTERMSIG(s));
  33.     }
  34.     printf("parent...\n");
  35.   }
  36.   return 0;
  37. }
复制代码


  • 执行结果


给指定进程发送信号(kill)

kill -[信号编号] [进程的pid]



僵尸进程

子进程已经终止,但是父进程还没有回收子进程的资源,这时候的子进程处于僵尸状态,成为僵尸进程。



代码示例



  • zombile.c
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/wait.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. int main(void){
  7.   pid_t pid;
  8.   pid=fork();
  9.   if(pid==-1){
  10.     perror("fork");
  11.     return 1;
  12.   }
  13.   if(pid==0){
  14.     exit(0);
  15.   }else{
  16.     sleep(20);
  17.     wait(NULL);
  18.   }
  19.   return 0;
  20. }
复制代码
在进程的虚拟地址空间加载新的映像

在子进程的虚拟地址空间加载新的影像,需要使用系统提供的一个家族的函数。
execl(3)
  1. #include <unistd.h>
  2. extern char **environ;
  3. int execl(const char *path,  const  char *arg, ...);
  4. int execlp(const char *file, const char *arg, ...);
  5. int execle(const char *path, const  char *arg,\
  6.               ..., char * const envp[]);
  7. int execv(const char *path, char *const argv[]);
  8. int execvp(const char *file, char *const argv[]);
  9. int execvpe(const   char  *file,  char *const argv[],
  10.                   char *const envp[]);
复制代码
execve(2)
  1. #include <unistd.h>
  2. int  execve(const  char  *filename, char *const argv[],\
  3.                   char *const envp[]);
  4. 相同的exec
  5. l list   
  6. v vector
  7. p PATH   
  8. e 环境变量
  9. 返回值:
  10. 成功调用永远不返回
  11. -1  错误   errno被设置
复制代码
代码示例


  • exec.c
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/wait.h>
  5. char *const ps_argv[]={"ps","-o","pid,ppid,pgrp,comm",NULL};
  6. int main(void){
  7.   pid_t pid;
  8.   
  9.   //创建子进程
  10.   pid=fork();
  11.   if(pid ==-1){
  12.     perror("fork");
  13.     return 1;
  14.   }
  15.   if(pid==0){
  16.     //加载新映像
  17.     //execl("/bin/ps","ps","-o",\
  18.     "pid,ppid,pgrp,comm",NULL);
  19.   
  20.     //execlp("ps","ps","-o",\
  21.     "pid,ppid,pgrp,comm",NULL);
  22.     execvp("ps",ps_argv);
  23.   }else{
  24.     wait(NULL);
  25.   }
  26.   return 0;
  27. }
复制代码


  • 执行结果


使用 system 启动新的可执行程序

  1. #include <stdlib.h>
  2. int system(const char *command);
  3. 功能:执行一个shell命令
  4. 参数:
  5. command:可执行命令
  6. 返回值:
  7. -1  错误
  8. 返回command的退出状态码。
复制代码
代码示例



  • system.c
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/wait.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. int main(void){
  7.   pid_t pid;
  8.   pid=fork();
  9.   if(pid==-1){
  10.     return 1;
  11.   }
  12.   if(pid==0){
  13.     execl("./myt","myt",NULL);
  14.     //system("myt");
  15.     exit(0);
  16.   }else{
  17.     wait(NULL);
  18.   }
  19.   return 0;
  20. }
复制代码


  • 执行结果

另外,作者在蓝桥云课上线了《Linux 操作系统原理剖析》,以 Linux 操作系统为基础对操作系统实现原理进行深入讲解,分析操作系统中的内存管理、进程管理、文件系统管理、设备管理、网络管理等几大子模块的实现原理。

如果想学此门课程,欢迎扫文末二维码优惠学!除此之外,大家还可选择教育优惠哦~

号外!号外!
蓝桥云课专属教育优惠重磅上线啦!

仅需完成学生认证
即享 5 折学生优惠券
▼扫码完成学生认证▼

▲课程优惠学▲

戳戳“阅读原文”直达课程页面!

来源:https://blog.csdn.net/MOY37RQW1JarN33BgZk/article/details/125288813
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表