Android C++系列:Linux进程(三)

简介: 如果一个进程已经终止,但是它的父进程尚未调用wait或waitpid对它进行清理,这时 的进程状态称为僵尸(Zombie)进程。任何进程在刚终止时都是僵尸进程,正常情况下,僵 尸进程都立刻被父进程清理了,为了观察到僵尸进程

image.png


wait/waitpid


僵尸进程: 子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程


孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号 进程init进程,称为init进程领养孤儿进程


#include <sys/types.h> 
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);


  • < -1 回收指定进程组内的任意子进程
  • -1 回收任意子进程
  • 0 回收和当前调用waitpid一个组的所有子进程 > 0 回收指定ID的子进程


一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还 保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止 则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用wait或waitpid获取这 些信息,然后彻底清除掉这个进程。我们知道一个进程的退出状态可以在Shell中用特殊变 量$?查看,因为Shell是它的父进程,当它终止时Shell调用wait或waitpid得到它的退出状 态同时彻底清除掉这个进程。


如果一个进程已经终止,但是它的父进程尚未调用wait或waitpid对它进行清理,这时 的进程状态称为僵尸(Zombie)进程。任何进程在刚终止时都是僵尸进程,正常情况下,僵 尸进程都立刻被父进程清理了,为了观察到僵尸进程,我们自己写一个不正常的程序,父进 程fork出子进程,子进程终止,而父进程既不终止也不调用wait清理子进程:


#include <unistd.h> 
#include <stdlib.h>
int main(void) {
  pid_t pid=fork(); 
  if(pid<0) {
    perror("fork");
    exit(1); 
  }
  if(pid>0) { /* parent */
    while(1); 
  }
  /* child */
  return 0; 
}


若调用成功则返回清理掉的子进程id,若调用出错则返回-1。父进程调用wait或 waitpid时可能会:


  • 阻塞(如果它的所有子进程都还在运行)。


  • 带子进程的终止信息立即返回(如果一个子进程已终止,正等待父进程读取其终止信息)。


  • 出错立即返回(如果它没有任何子进程)。


这两个函数的区别是:


  • 如果父进程的所有子进程都还在运行,调用wait将使父进程阻塞,而调用waitpid时如 果在options参数中指定WNOHANG可以使父进程不阻塞而立即返回0。


  • wait等待第一个终止的子进程,而waitpid可以通过pid参数指定等待哪一个子进程。


可见,调用wait和waitpid不仅可以获得子进程的终止信息,还可以使父进程阻塞等待子进 程终止,起到进程间同步的作用。如果参数status不是空指针,则子进程的终止信息通过 这个参数传出,如果只是为了同步而不关心子进程的终止信息,可以将status参数指定为 NULL。


例 waitpid


#include <sys/types.h> 
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
  pid_t pid;
  pid = fork(); 
  if (pid < 0) {
    perror("fork failed");
    exit(1); 
  }
  if (pid == 0) { 
    int i;
    for (i = 3; i > 0; i--) { 
      printf("This is the child\n"); 
      sleep(1);
    }
    exit(3); 
  } else {
    int stat_val;
    waitpid(pid, &stat_val, 0);
    if (WIFEXITED(stat_val))
      printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
    else if (WIFSIGNALED(stat_val))
      printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
  }
  return 0;
}


wait阻塞函数,阻塞等待子进程结束 waitpid 4种情况 < -1 = -1 = 0 > 0


  • 进程的退出状态
  • 非阻塞标志,WNOHANG
  • 获取进程退出状态的函数见manpages
  • 调用进程若无子进程,则wait出错返回


总结


本文介绍了僵尸进程和孤儿进程的概念解决方案。僵尸进程: 子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程;孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号 进程init进程,称为init进程领养孤儿进程。

目录
相关文章
|
15天前
|
NoSQL Unix Linux
Linux下的系统编程——守护进程、线程(十二)
Linux下的系统编程——守护进程、线程(十二)
9 0
Linux下的系统编程——守护进程、线程(十二)
|
15天前
|
消息中间件 Linux
Linux下的系统编程——进程间的通信(九)
Linux下的系统编程——进程间的通信(九)
28 1
Linux下的系统编程——进程间的通信(九)
|
15天前
|
Linux
Linux下的系统编程——进程的执行与回收(八)
Linux下的系统编程——进程的执行与回收(八)
27 1
Linux下的系统编程——进程的执行与回收(八)
|
15天前
|
NoSQL Linux Shell
Linux下的系统编程——认识进程(七)
Linux下的系统编程——认识进程(七)
35 1
Linux下的系统编程——认识进程(七)
|
15天前
|
存储 安全 数据管理
进程概念【linux】
进程概念【linux】
|
15天前
|
Linux
百度搜索:蓝易云【深入解析Linux进程内存:VSS、RSS、PSS、USS及查看方式】
通过以上方法,你可以深入了解Linux进程的内存使用情况,包括VSS、RSS、PSS、USS等指标,帮助你进行性能优化和资源管理。
29 12
|
16天前
|
监控 NoSQL Linux
《Linux中的进程:任务管理的独门技能大揭秘》(ps、top等)
《Linux中的进程:任务管理的独门技能大揭秘》(ps、top等)
24 0
|
17天前
|
Linux
百度搜索:蓝易云【Linux系统ps命令:查看正在运行的进程】
通过这些简洁的ps命令用法,你可以方便地查看Linux系统中正在运行的进程信息。
17 1
|
19天前
|
Ubuntu 网络协议 Linux
【Linux】Android平板上远程连接Ubuntu服务器code-server进行代码开发
【Linux】Android平板上远程连接Ubuntu服务器code-server进行代码开发
19 0
|
20天前
|
Ubuntu Linux Shell
【Linux操作系统】探秘Linux奥秘:进程与任务管理的解密与实战
【Linux操作系统】探秘Linux奥秘:进程与任务管理的解密与实战
24 0

相关产品

  • 云迁移中心