当前位置: 首页 > news >正文

Linux进程状态

1. 一般的操作系统学科进程状态

1.1 Linux 内核调度系统和进程运行机制:

核心概念:

  • Linux 使用 task_struct 描述进程,链入运行队列中。
  • 每个 CPU 有一个 runqueue,调度器从中选择任务运行。
  • 每个进程被分配一个时间片,时间到了会被强制切换。
  • 即使进程陷入死循环,也不会永远占用 CPU(如 while(1))。
  • 多个进程在一个时间段内看似“同时”运行,是因为被快速轮换执行。
  • 调度器负责将准备好的任务从 runqueue 中调度上 CPU 执行(状态为 TASK_RUNNING)。

1.2 操作系统中的进程阻塞机制

  1. 进程请求键盘输入

    1. 操作系统发现键盘无数据可读。

    2. 进程进入阻塞状态,挂到键盘设备的 waitqueue 上。

  2. 系统内存紧张

    1. 操作系统将部分阻塞进程换出(即保存到磁盘 swap 区),释放物理内存。

  3. 键盘收到数据

    1. 操作系统通过中断机制通知。

    2. 唤醒在 waitqueue 中等待键盘输入的进程。

    3. 若进程被换出,还会将其从磁盘换入内存。

  4. 进程恢复运行

2. Linux进程状态的维护

2.1 Linux内核源代码

为了弄明白正在运行的进程是什么意思,我们需要看到进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫任务)
在Linux源代码:

/** The task state array is a strange "bitmap" of* reasons to sleep. Thus "running" is zero, and* you can test for combinations of others with* simple bit tests.*/
static const char * const task_state_array[] = {/* states in TASK_REPORT: */"R (running)",		/* 0x00 */"S (sleeping)",		/* 0x01 */"D (disk sleep)",	/* 0x02 */"T (stopped)",		/* 0x04 */"t (tracing stop)",	/* 0x08 */"X (dead)",		/* 0x10 */"Z (zombie)",		/* 0x20 */"P (parked)",		/* 0x40 *//* states beyond TASK_REPORT: */"I (idle)",		/* 0x80 */
};

2.2 进程状态

R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

#include<stdio.h>
int main()
{while(1);return 0;
}


 S睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫可中断睡眠(interruptible sleep))。

#include<stdio.h>
int main()
{int n=0;scanf("%d",&n);//等待键盘输入,进入阻塞状态return 0;
}


D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

D 状态的关键特征:

  • 不能被 kill -9 杀死。
  • 不能被调度唤醒,除非资源就绪。
  • 通常发生在驱动程序里,特别是 调用等待资源的函数(比如读取硬盘时阻塞)。

注意:

  • 如果你在内核代码或驱动里使用 TASK_UNINTERRUPTIBLE + schedule(),却忘了设置条件唤醒(比如 wake_up()),那这个进程就会永久卡在 D 状态,用户空间无法杀掉它。
  • 通常在等待硬件响应(如磁盘响应、USB响应)时,才需要 D 状态。
  • 用户态程序无法主动进入 D 状态,只能是调用了某些内核接口后,被动地处于 D 状态。

T停止状态(stopped):可以通过发送SIGSTOP信号来停止进程。这个被暂停的进程可以通过发送SIGCONT信号让进程继续运行。

#include <stdio.h>
#include<unistd.h>
int main()
{while (1){printf("I am a process\n");sleep(1);}return 0;
}

停止:

恢复运行: 


t状态(tracing stop) :进程被调试器(如 gdb)以 ptrace 方式挂起,正在停止(Stop)中。


X死亡状态:这个状态只是一个返回状态,不会在任务列表里看到这个状态。一旦状态为 X,内核很快就会释放 task_struct。


2.3 进程状态查看

ps aux:显示所有进程的摘要信息

命令含义:

  • a:显示所有用户的进程

  • u:显示用户/资源占用情况(User格式)

  • x:显示没有控制终端的进程

ps axj:显示父子关系 & 调试/调度相关信息

命令含义:

  • a:所有终端的进程

  • x:包含没有终端的进程

  • j:jobs 格式,显示进程层次结构(父子关系)

 

字段含义

字段含义
PPID父进程 ID
PID当前进程 ID
PGID进程组 ID
SID会话 ID
TPGID前台进程组 ID
STAT状态(比如 R, S, D, T, t
COMMAND启动命令

 2.4 Z(zombie)-僵尸进程

  • 僵尸状态(Zombie)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸(死)进程。
  • 僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
  • 所以,只要子进程退出,父进程还在运行,但是父进程没有读取子进程状态,子进程进入Z状态。进程的相关信息尤其是task_struct结构体不能被释放。
#include <stdio.h>
#include<unistd.h>
int main()
{pid_t ret=fork();if(ret==0){//childprintf("I am child\n");return 0;}else if(ret>0){printf(" I am father\n");sleep(20);}return 0;
}

僵尸进程的危害

  • 进程的退出状态必须被维持下去,因为它要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那么子进程就会一直处于Z状态。
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
  • 如果一个父进程创建了很多子进程,但是不回收,就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  • 内存泄漏

2.5 孤儿进程

  • 父进程先退出,子进程就被称为孤儿进程
  • 孤儿进程被1号init(操作系统)领养,并由init进程回收资源
#include <stdio.h>
#include <unistd.h>int main()
{pid_t ret = fork();if (ret == 0){// childprintf("I am child\n");sleep(30);}else if (ret > 0){printf(" I am father\n");sleep(5);return 0;}return 0;
}

http://www.xdnf.cn/news/43021.html

相关文章:

  • 05【数据基石·下】复合类型:元组 (Tuple) 与数组 (Array) 的定长世界
  • 【MySQL】Read view存储的机制,记录可见分析
  • *数字信号基础
  • Nginx在微服务架构项目(Spring Cloud)中的强大作用
  • 【智驾中的大模型 -3】VLA 在自动驾驶中的应用
  • 运维侠职场日记9:用DeepSeek三天通关详解自动化操作pdf批量提取PDF文字将PDF转Word文档(附上脚本代码)
  • SpringBoot实战3
  • jupyter切换存储路径
  • FFmpeg:M3U8的AES加密
  • Mac-VScode-C++环境配置
  • 如何在 Go 中创建和部署 AWS Lambda 函数
  • 【linux基本工具的使用 yum vim gdb 以及makefile自动化构建项目】
  • 学习笔记十九——Rust多态
  • MFC文件-写MP4
  • Python打包程序为exe文件(py2exe)
  • AES (高级加密标准)
  • (mac)Grafana监控系统之监控Linux的Redis
  • 基于Matlab求解矩阵电容等效容值
  • 解决vscode找不到Python自定义模块,报错No module named ‘xxx‘
  • MySQL数据库(基础篇)
  • Gitlab runner 安装和注册
  • 解决模拟器打开小红书设备异常问题
  • n8n 中文系列教程_04.半开放节点深度解析:Code与HTTP Request高阶用法指南
  • 2025年渗透测试面试题总结-拷打题库08(题目+回答)
  • Docker Compose 外部网络(`external: true`)与内部网络的区别
  • 【AI图像创作变现】02工具推荐与差异化对比
  • 用于手部康复设备的TinyML语音分类嵌入式人工智能模块
  • 大模型day4 - LangChain
  • Jsp技术入门指南【九】详细讲解JSTL
  • Linux 文件系统目录结构详解