【进程控制(进程退出、孤儿进程、僵尸进程)_Linux】

2024-02-11 08:18

本文主要是介绍【进程控制(进程退出、孤儿进程、僵尸进程)_Linux】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        • 01 / 进程退出
        • 02 / 孤儿进程
        • 03 / 僵尸进程
        • 04 / 进程回收
          • wait()函数
          • 退出信息相关宏函数
          • waitpid()函数

01 / 进程退出
//标准C库函数
#include <stdlib.h>
void exit(int status);//Linux系统函数
#include <unistd.h>
void _exit(int status);//status参数:是进程退出时的一个状态信息。父进程回收子进程资源的时候可以获取到。

在这里插入图片描述
示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() {printf("hello\n");printf("world");// exit(0);_exit(0);return 0;
}
02 / 孤儿进程

父进程运行结束,但子进程还在运行(未运行结束),这样的子进程就称为孤儿进程(Orphan Process)。

◼ 每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为 init ,而 init 进程会循环地 wait() 它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init 进程就会代表党和政府出面处理它的一切善后工作。

◼ 因此孤儿进程并不会有什么危害。

示例

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>int main() {// 创建子进程pid_t pid = fork();// 判断是父进程还是子进程if(pid > 0) {printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());} else if(pid == 0) {sleep(1);// 当前是子进程printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid());}// for循环for(int i = 0; i < 3; i++) {printf("i : %d , pid : %d\n", i , getpid());}return 0;
}

在这里插入图片描述

03 / 僵尸进程

◼ 每个进程结束之后, 都会释放自己地址空间中的用户区数据,内核区的 PCB 没有办法自己释放掉,需要父进程去释放。

进程终止时,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。

僵尸进程不能被 kill -9 杀死这样就会导致一个问题,如果父进程不调用 wait() 或 waitpid() 的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害,应当避免。

示例

在这里插入图片描述
在这里插入图片描述

04 / 进程回收

◼ 在每个进程退出的时候,内核释放该进程所有的资源、包括打开的文件、占用的内存等。但是仍然为其保留一定的信息,这些信息主要主要指进程控制块PCB的信息(包括进程号、退出状态、运行时间等)。

◼ 父进程可以通过调用wait或waitpid得到它的退出状态同时彻底清除掉这个进程。

◼ wait() 和 waitpid() 函数的功能一样,区别在于,wait() 函数会阻塞,waitpid() 可以设置不阻塞,waitpid() 还可以指定等待哪个子进程结束。

◼ 注意:一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环。

wait()函数
   #include <sys/types.h>#include <sys/wait.h>pid_t wait(int *wstatus);功能:等待任意一个子进程结束,如果任意一个子进程结束了,次函数会回收子进程的资源。参数:int *wstatus进程退出时的状态信息,传入的是一个int类型的地址,传出参数。返回值:- 成功:返回被回收的子进程的id- 失败:-1 (所有的子进程都结束,调用函数失败)调用wait函数的进程会被挂起(阻塞),直到它的一个子进程退出或者收到一个不能被忽略的信号时才被醒(相当于继续往下执行)如果没有子进程了,函数立刻返回,返回-1;如果子进程都已经结束了,也会立即返回,返回-1.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main() {// 有一个父进程,创建5个子进程(兄弟)pid_t pid;// 创建5个子进程for(int i = 0; i < 5; i++) {pid = fork();if(pid == 0) {break;}}if(pid > 0) {// 父进程while(1) {printf("parent, pid = %d\n", getpid());// int ret = wait(NULL);int st;int ret = wait(&st);if(ret == -1) {break;}if(WIFEXITED(st)) {// 是不是正常退出printf("退出的状态码:%d\n", WEXITSTATUS(st));}if(WIFSIGNALED(st)) {// 是不是异常终止printf("被哪个信号干掉了:%d\n", WTERMSIG(st));}printf("child die, pid = %d\n", ret);sleep(1);}} else if (pid == 0){// 子进程while(1) {printf("child, pid = %d\n",getpid());    sleep(1);       }exit(0);}return 0; // exit(0)
}
退出信息相关宏函数
WIFEXITED(status)0,进程正常退出
◼ WEXITSTATUS(status) 	如果上宏为真,获取进程退出的状态(exit的参数)◼ WIFSIGNALED(status)0,进程异常终止
◼ WTERMSIG(status) 		如果上宏为真,获取使进程终止的信号编号◼ WIFSTOPPED(status)0,进程处于暂停状态
◼ WSTOPSIG(status) 		如果上宏为真,获取使进程暂停的信号的编号
◼ WIFCONTINUED(status)0,进程暂停后已经继续运行
waitpid()函数
    #include <sys/types.h>#include <sys/wait.h>pid_t waitpid(pid_t pid, int *wstatus, int options);功能:回收指定进程号的子进程,可以设置是否阻塞。参数:- pid:pid > 0 :   某个子进程的pidpid = 0 :   回收当前进程组的所有子进程    pid = -1 :  回收所有的子进程,相当于 wait()  (最常用)pid < -1 :  某个进程组的组id的绝对值,回收指定进程组中的子进程- options:设置阻塞或者非阻塞0 :         阻塞WNOHANG :   非阻塞- 返回值:> 0 :       返回子进程的id= 0 :       options=WNOHANG, 表示还有子进程或者= -1 :     错误,或者没有子进程了
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main() {// 有一个父进程,创建5个子进程(兄弟)pid_t pid;// 创建5个子进程for(int i = 0; i < 5; i++) {pid = fork();if(pid == 0) {break;}}if(pid > 0) {// 父进程while(1) {printf("parent, pid = %d\n", getpid());sleep(1);int st;// int ret = waitpid(-1, &st, 0);int ret = waitpid(-1, &st, WNOHANG);if(ret == -1) {break;} else if(ret == 0) {// 说明还有子进程存在continue;} else if(ret > 0) {if(WIFEXITED(st)) {// 是不是正常退出printf("退出的状态码:%d\n", WEXITSTATUS(st));}if(WIFSIGNALED(st)) {// 是不是异常终止printf("被哪个信号干掉了:%d\n", WTERMSIG(st));}printf("child die, pid = %d\n", ret);}}} else if (pid == 0){// 子进程while(1) {printf("child, pid = %d\n",getpid());    sleep(1);       }exit(0);}return 0; 
}

这篇关于【进程控制(进程退出、孤儿进程、僵尸进程)_Linux】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/699318

相关文章

Python如何精准判断某个进程是否在运行

《Python如何精准判断某个进程是否在运行》这篇文章主要为大家详细介绍了Python如何精准判断某个进程是否在运行,本文为大家整理了3种方法并进行了对比,有需要的小伙伴可以跟随小编一起学习一下... 目录一、为什么需要判断进程是否存在二、方法1:用psutil库(推荐)三、方法2:用os.system调用

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文