linux 基础,你学会了吗?

admin 2022年7月1日18:49:37linux 基础,你学会了吗?已关闭评论16 views字数 4804阅读16分0秒阅读模式
图片
点击蓝字 关注我们
图片

linux 基础,你掌握了几个?


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


图片


进程的退出

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


void exit(int status);

#include <stdlib.h>void exit(int status);功能:终止进程参数:status:退出状态码。status&0377的值给父进程。返回值:永远不返回。

代码示例

  • test.c

#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)

  • on_exit.c

#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);}

  • 执行结果

linux 基础,你学会了吗?

atexit

atexit(3)

#include <stdlib.h>int atexit(void (*function)(void));功能:注册一个函数给进程,在进程终止的时候调用该函数参数:function:指定了要注册的函数的名字返回值:0    成功非0   错误

代码示例(atexit)

  • atexit.c

#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 进程,这种进程被成为孤儿进程。


代码示例

  • lonely.c

#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

代码示例

  • wait.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{    //等待子进程的结束    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[]);相同的execl list   v vectorp 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 折学生优惠券


▼扫码完成学生认证▼

图片

▲课程优惠学▲

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

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月1日18:49:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   linux 基础,你学会了吗?https://cn-sec.com/archives/1150391.html