Linux进程(三) --- 状态和优先级

运行,阻塞,挂起

运行 (Running)

当一个进程处于运行状态时,它正在使用CPU执行指令。进程在以下两种情况下可能被认为是运行状态:

  1. 实际运行(Running on CPU): 进程当前正在CPU上执行。
  2. 可运行(Runnable): 进程准备好运行,只是在等待CPU资源。

在任务管理器中,处于运行状态的进程通常会显示为R

阻塞 (Blocked)

当一个进程被阻塞时,它正在等待某些事件完成,无法继续执行。阻塞通常发生在进程需要等待某种资源的情况,例如:

  • 等待I/O操作完成(如读取文件或网络数据)
  • 等待某个信号或条件变量

在任务管理器中,阻塞状态的进程通常会显示为D(不可中断的睡眠)或S(可中断的睡眠)。

挂起 (Suspended)

挂起状态表示进程已被暂停,暂时停止了运行。挂起可以通过以下方式发生:

  • 显式挂起(Suspended by signal): 进程收到一个挂起信号(如SIGSTOP),并停止执行,直到收到继续信号(如SIGCONT)。
  • 后台挂起(Suspended by job control): 用户在shell中使用命令(如Ctrl+Z)将前台进程挂起并转入后台。

在任务管理器中,挂起状态的进程通常会显示为T(stopped by job control signal)。

总结

  • 运行(Running): 进程正在使用CPU或准备使用CPU。
  • 阻塞(Blocked): 进程在等待某个事件或资源。
  • 挂起(Suspended): 进程已被暂停,等待继续执行的信号。

进程的状态与切换

  • 运行(Running):

    R (Running): 进程正在CPU上运行或准备运行。
  • 可中断睡眠(Interruptible Sleep):

    S (Sleeping): 进程正在等待某个事件(如I/O操作)完成,可以被信号中断唤醒。
  • 不可中断睡眠(Uninterruptible Sleep):

    D (Uninterruptible sleep): 进程在等待某个无法中断的事件(如设备I/O操作)完成,通常不会响应信号。
  • 停止(Stopped):

    T (Stopped): 进程已被停止,可以由用户或调试器发出信号(如SIGSTOP)造成。
  • 僵尸(Zombie):

    Z (Zombie): 进程已终止,但其进程表项仍然保留,等待父进程读取其退出状态。
  • 挂起(Suspended):

    挂起状态是停止状态的一种表现,通常是通过Ctrl+ZSIGSTOP信号实现的。

进程状态切换的方法

进程状态之间的切换是由内核根据进程的行为和系统事件进行管理的。常见的状态切换及其触发条件如下:

  • 从运行(Running)到可中断睡眠(Sleeping):

    • 进程执行阻塞I/O操作,如读写文件,等待网络数据等。
    • 调用系统调用如sleep()select()poll()或等待某个事件。
  • 从可中断睡眠(Sleeping)到运行(Running):

    • I/O操作完成或事件发生,唤醒等待的进程。
    • 进程收到一个信号,导致其从睡眠状态被中断。
  • 从运行(Running)到不可中断睡眠(Uninterruptible sleep):

    • 进程执行某些不可中断的系统调用或等待硬件设备响应。
  • 从不可中断睡眠(Uninterruptible sleep)到运行(Running):

    • 不可中断的系统调用或硬件设备操作完成,进程重新变为可运行。
  • 从运行(Running)到停止(Stopped):

    • 进程收到SIGSTOPSIGTSTP(由Ctrl+Z触发)等信号。
    • 用户在调试过程中手动暂停进程。
  • 从停止(Stopped)到运行(Running):

    • 进程收到SIGCONT信号,继续执行。
  • 从运行(Running)到僵尸(Zombie):

    • 进程正常退出(调用exit()),但其父进程尚未调用wait()waitpid()读取其退出状态。
  • 从僵尸(Zombie)到终止(Terminated):

    • 父进程调用wait()waitpid()读取僵尸进程的退出状态后,僵尸进程彻底从系统中移除。

僵尸进程

什么是僵尸进程?

僵尸进程是已经终止执行但仍然在进程表中保留的进程。它保留在进程表中的原因是为了让其父进程读取它的退出状态。这种状态的进程不会占用系统资源(如CPU和内存),但会占用一个进程表项。

僵尸进程的产生

当一个进程结束时(通过调用exit()或返回main()函数),操作系统会清理它所占用的大部分资源,但仍会保留一个记录,包括进程的退出状态。这是因为Unix-like系统采用了父子进程关系的机制,父进程需要通过调用wait()waitpid()系统调用来读取子进程的退出状态。

具体步骤如下:

  1. 子进程终止: 子进程调用exit()终止运行。
  2. 内核保留进程信息: 内核会保留子进程的退出状态和其他信息,以便父进程读取。
  3. 子进程进入僵尸状态: 子进程的状态变为僵尸状态,直到父进程读取它的退出状态。
  4. 父进程读取退出状态: 父进程调用wait()waitpid()读取子进程的退出状态,内核随即清理僵尸进程的剩余信息,从进程表中移除该进程。

为什么会有僵尸进程?

僵尸进程存在的主要原因是确保父进程能够得到子进程的退出信息。这对于进程间通信和进程管理非常重要。通过这种机制,父进程可以知道子进程是正常终止还是由于错误终止,并可以基于此信息进行相应的处理。

僵尸进程的问题

虽然僵尸进程本身不占用大量系统资源,但大量的僵尸进程会导致进程表项耗尽,从而阻止系统创建新进程。因此,管理僵尸进程非常重要。

如何处理僵尸进程?

  • 确保父进程读取子进程的退出状态: 父进程应该使用wait()waitpid()系统调用来处理子进程的退出状态。如果父进程没有执行这一步,子进程就会变成僵尸进程。
  • 孤儿进程和init进程: 如果父进程终止而没有处理子进程的退出状态,子进程会成为孤儿进程。孤儿进程会被init进程(PID为1)接管,init进程会自动处理这些子进程的退出状态,从而避免僵尸进程的产生。
  • 信号处理: 可以通过设置父进程的信号处理函数,当子进程终止时捕获SIGCHLD信号并调用waitpid()来处理退出状态。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>void handle_sigchld(int sig) {// 使用waitpid处理所有已终止的子进程while (waitpid(-1, NULL, WNOHANG) > 0) {// Nothing to do here}
}int main() {signal(SIGCHLD, handle_sigchld);  // 注册SIGCHLD信号处理程序pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) {// 子进程printf("Child process: %d\n", getpid());exit(0);} else {// 父进程printf("Parent process: %d\n", getpid());sleep(10);  // 让父进程等待足够长的时间}return 0;
}

孤儿进程

孤儿进程(Orphan Process)是指其父进程已经终止,而它自身仍然在运行的进程。当一个进程终止时,其子进程不会自动终止,而是会变成孤儿进程。为了确保系统的稳定性和资源的合理利用,孤儿进程会被系统中的一个特殊进程,即init进程(PID为1)接管。

孤儿进程的处理

当孤儿进程被init进程接管后,init进程会成为这些孤儿进程的新父进程,并负责处理它们的退出状态,避免它们变成僵尸进程。

具体过程

  1. 父进程终止: 一个进程终止而其子进程仍在运行。
  2. 孤儿进程产生: 子进程因为其父进程终止而成为孤儿进程。
  3. init进程接管: 操作系统会将孤儿进程的父进程重新设置为init进程。
  4. init进程处理: 当这些孤儿进程终止时,init进程会调用wait()waitpid()读取它们的退出状态,从而防止它们变成僵尸进程。

示例

下面是一个简单的C语言示例,演示了孤儿进程的产生过程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid = fork();if (pid < 0) {// fork失败perror("fork failed");exit(1);} else if (pid == 0) {// 子进程printf("Child process, PID: %d, Parent PID: %d\n", getpid(), getppid());sleep(5);  // 保持子进程运行一段时间,确保父进程先终止printf("Child process after sleep, PID: %d, New Parent PID: %d\n", getpid(), getppid());exit(0);} else {// 父进程printf("Parent process, PID: %d\n", getpid());exit(0);  // 父进程立即终止}return 0;
}

在这个示例中:

  1. 父进程创建一个子进程。
  2. 父进程终止,而子进程保持运行。
  3. 子进程在睡眠5秒后醒来,并输出其新的父进程PID,此时父进程已经是init进程。
    输出示例:Parent process, PID: 12345
    Child process, PID: 12346, Parent PID: 12345
    Child process after sleep, PID: 12346, New Parent PID: 1
    

    在输出中可以看到,子进程最初的父进程PID是原父进程的PID,当原父进程终止后,子进程的父进程PID变为1,即init进程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/13268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何利用R包进行主成分分析和可视化

一. 使用R包“FactoMineR”进行主成分分析&#xff08;PCA&#xff09; 基本步骤如下&#xff1a; 安装和加载包&#xff1a;如果尚未安装&#xff0c;首先安装“FactoMineR”包&#xff0c;然后加载它&#xff1a; install.packages("FactoMineR")library(FactoM…

在springboot项目中自定义404页面

今天点击菜单的时候不小心点开了一个不存在的页面&#xff0c;然后看到浏览器给的一个默认的404页面 后端的程序员都觉得这页面太丑了&#xff0c;那么怎么能自定义404页面呢&#xff1f; 很简单&#xff0c;在我们的springboot的静态资源目录下创建一个error包&#xff0c;然…

ue引擎游戏开发笔记(41)——行为树的建立(2)--丰富ai行为:巡逻后返回原处

1.需求分析&#xff1a; 就敌人ai而言&#xff0c;追踪到敌人有可能丢失目标&#xff0c;丢失目标后应该能返回原来位置&#xff0c;实现这一功能。 2.操作实现&#xff1a; 1.思路&#xff1a;利用clear value函数&#xff0c;禁用掉当前的追踪功能&#xff0c;执行之后的返…

积温空间分布数据、气温分布数据、日照数据、降雨量分布、太阳辐射数据、地表径流数据、土地利用数据、npp数据、ndvi数据

引言 积温是某一时段内逐日平均气温之和,它是研究植物生长、发育对热量的要求和评价热量资源的一种指标,是影响植物生长的重要因素之一&#xff0c;对指导农业生产和生态建设具有非常重要的意义。作为重要的气候资源&#xff0c;积温与其它资源的区别在于存在很大的地域差异和时…

Python | Leetcode Python题解之第91题解码方法

题目&#xff1a; 题解&#xff1a; class Solution:def numDecodings(self, s: str) -> int:n len(s)# a f[i-2], b f[i-1], c f[i]a, b, c 0, 1, 0for i in range(1, n 1):c 0if s[i - 1] ! 0:c bif i > 1 and s[i - 2] ! 0 and int(s[i-2:i]) < 26:c aa,…

C++——STL容器——List

1. 前言 List也是STL容器的一种&#xff0c;是C提供的链表结构的容器。C中所提供的list是双向带头循环链表&#xff0c;我们这篇文章通过自己模拟实现来学习list的使用。 为了避免和库中的命名冲突&#xff0c;也为了封装的考虑&#xff0c;我们将我们的list放入一个命名空间之…

微服架构基础设施环境平台搭建 -(七)Kubesphere pod内安装vimping命令

微服架构基础设施环境平台搭建 -&#xff08;七&#xff09;Kubesphere pod安装vim&ping命令 在K8s集群运维过程&#xff0c;需要进入pod容器内通过ping来测试网络是否通畅&#xff0c;或使用vim进行编辑文件&#xff0c;但是pod容器默认情况下是不支持ping、vim命令的&…

2024.05.15学习记录

1、完成Ts重构Axios项目中更多功能的开发 2、刷题&#xff1a;二叉树&#xff08;代码回忆录&#xff09; 3、复习diff算法源码解读

C语言 | Leetcode C语言题解之第91题解码方法

题目&#xff1a; 题解&#xff1a; int numDecodings(char* s) {int n strlen(s);// a f[i-2], b f[i-1], c f[i]int a 0, b 1, c;for (int i 1; i < n; i) {c 0;if (s[i - 1] ! 0) {c b;}if (i > 1 && s[i - 2] ! 0 && ((s[i - 2] - 0) * 10…

C++|树形关联式容器(set、map、multiset、multimap)介绍使用

目录 一、关联式容器介绍 1.1概念 1.2键值对 1.3树形结构的关联式容器 1.3.1pair模板介绍 1.3.2make_pair的介绍 二、set的介绍和使用 2.1set介绍 2.2set使用 2.2.1构造 2.2.2容量 2.2.3修改 三、map的介绍和使用 3.1map介绍 3.2map使用 3.2.1构造 3.2.2容量 …

相机模型的内参、外参

相机模型的内参、外参 文章目录 相机模型的内参、外参1. 针孔模型、畸变模型&#xff08;内参&#xff09;2. 手眼标定&#xff08;外参&#xff09; Reference 这篇笔记主要参考&#xff1a;slam十四讲第二版&#xff08;高翔&#xff09; 相机将三维世界中的坐标点&#xff…

PDK安装及简介

目录 PDK简介 pdk安装 Standard Cell Library简介 IO Library简介 PDK简介 PDK&#xff1a;全称Process Design Kit&#xff0c;是工艺设计工具包的缩写&#xff0c;是制造和设计之间的沟通桥梁&#xff0c;是模拟电路设计的起始点。 具体来说&#xff0c;PDK是代工厂(FAB…

使用Docker进行Jmeter分布式搭建

大家好&#xff0c;随着技术的不断发展&#xff0c;对性能测试的要求也日益提高。在这样的背景下&#xff0c;如何利用 Docker 来巧妙地搭建 Jmeter 分布式成为了关键所在。现在&#xff0c;就让我们开启这场探索之旅&#xff0c;揭开其神秘的面纱。前段时间给大家分享了关于 L…

通信指挥类装备(多链路聚合设备)-应急通信指挥解决方案

现场通信指挥系统是一种功能全面的便携式音视频融合指挥通信平台&#xff0c;可实现现场应急救援指挥、多种通信手段融合、现场通信组网等功能&#xff0c;是现场指挥系统的延伸。 多链路聚合设备&#xff0c;是一款通信指挥类装备&#xff0c;具有 4G/5G&#xff0c;专网&…

Free RTOS中Semaphore(二值信号量)的使用介绍

目录 概述 1 使用STM32Cube 配置信号量 1.1 引子 1.2 STM32Cube中配置FreeRTOS 1.3 STM32Cube生成Project 2 cmsis_os中信号量接口函数 2.1 函数&#xff1a;osSemaphoreNew 2.2 函数&#xff1a;osSemaphoreGetName 2.3 函数&#xff1a;osSemaphoreAcquire 2.4 函数…

设计模式:外观模式(Facade)

设计模式&#xff1a;外观模式&#xff08;Facade&#xff09; 设计模式&#xff1a;外观模式&#xff08;Facade&#xff09;模式动机模式定义模式结构时序图模式实现在单线程环境下的测试在多线程环境下的测试模式分析优缺点适用场景应用场景模式扩展参考 设计模式&#xff1…

【Open AI】GPT-4o深夜发布:视觉、听觉跨越式升级

北京时间5月14日1点整&#xff0c;OpenAI 召开了首场春季发布会&#xff0c;CTO Mira Murati 在台上和团队用短短不到30分钟的时间&#xff0c;揭开了最新旗舰模型 GPT-4o 的神秘面纱&#xff0c;以及基于 GPT-4o 的 ChatGPT&#xff0c;均为免费使用。 本文内容来自OpenAI网站…

人工智能|深度学习——YOLOV8结构图

YoloV8相对于YoloV5的改进点&#xff1a; Replace the C3 module with the C2f module.Replace the first 6x6 Conv with 3x3 Conv in the Backbone.Delete two Convs (No.10 and No.14 in the YOLOv5 config).Replace the first 1x1 Conv with 3x3 Conv in the Bottleneck.Use…

【图神经网络——消息传递】

消息传递机制 画图先&#xff1a;导包&#xff1a;画图&#xff1a; 实现消息传递&#xff1a;例子一&#xff1a;例子二&#xff1a; 画图先&#xff1a; 导包&#xff1a; import networkx as nx import matplotlib.pyplot as plt import torch from torch_geometric.nn im…

Linux操作系统最著名的两大系列Red Hat和Debian

Linux操作系统可以根据其背后的项目或社区分为不同的系列&#xff0c;其中最著名的两大系列是Red Hat系列和Debian系列。 1.著名的两大系列是Red Hat和Debian Red Hat系列&#xff1a; Red Hat Enterprise Linux (RHEL)&#xff1a;这是Red Hat公司推出的企业级操作系统&#…