当前位置:首页>Linux>从0开始了掌握Linux进程(2)

从0开始了掌握Linux进程(2)

  • 2026-10-11 06:08:48
从0开始了掌握Linux进程(2)

四、进程状态:生命周期管理

4.1 进程状态的设计意义

问题背景:CPU资源有限,进程数量众多。如何高效管理进程的执行顺序和资源分配?

解决方案:引入进程状态,实现进程的有序调度。

4.2 Linux进程状态详解

状态定义(Linux内核源码):

static const char *const task_state_array[] = {    "R (running)",     /* 运行状态 */    "S (sleeping)",    /* 睡眠状态 */    "D (disk sleep)",  /* 磁盘休眠 */    "T (stopped)",     /* 停止状态 */    "t (tracing stop)", /* 跟踪停止 */    "X (dead)",        /* 死亡状态 */    "Z (zombie)",      /* 僵尸状态 */};

状态说明:

状态
含义
实际场景
R (Running)
运行或就绪
进程正在执行或在运行队列等待
S (Sleeping)
可中断睡眠
等待事件完成(如等待输入)
D (Disk Sleep)
不可中断睡眠
等待IO完成(如磁盘读写)
T (Stopped)
停止
被信号暂停(如调试断点)
Z (Zombie)
僵尸
已退出但父进程未回收

4.3 僵尸进程:危害与预防

形成原因:子进程退出,父进程未调用wait()读取退出状态。

危害: - PCB无法释放,占用内存 - 大量僵尸进程导致内存泄漏 - 系统资源浪费

示例代码:

#include#include#includeintmain(){    pid_t pid = fork();    if (pid > 0) {        // 父进程:不回收子进程        printf("父进程PID: %d,睡眠30秒\n", getpid());        sleep(30);    }    else if (pid == 0) {        // 子进程:5秒后退出        printf("子进程PID: %d,即将成为僵尸\n", getpid());        sleep(5);        exit(0);    }    return 0;}

查看僵尸进程:

# 编译运行gcc zombie.c -o zombie./zombie# 另一个终端查看ps aux | grep zombie# 输出: 表示僵尸状态

预防方法:

// 父进程调用wait()回收子进程#includewait(NULL);  // 或 waitpid()

4.4 孤儿进程:自动领养

形成原因:父进程先退出,子进程成为孤儿。

处理机制:被init进程(PID=1)领养,由init负责回收。

示例代码:

#include #include #include int main() {    pid_t pid = fork();    if (pid > 0) {        // 父进程:3秒后退出        printf("父进程PID: %d,即将退出\n", getpid());        sleep(3);        exit(0);    }    else if (pid == 0) {        // 子进程:继续运行        printf("子进程PID: %d,父进程PID: %d\n", getpid(), getppid());        sleep(10);        printf("子进程被领养,新父进程PID: %d\n", getppid());    }    return 0;}

五、进程优先级:资源竞争的仲裁

5.1 优先级的必要性

问题背景:CPU资源稀缺,进程众多。如何公平高效分配CPU时间?

解决方案:引入优先级机制,重要进程优先执行。

5.2 PRI与NI的关系

概念辨析: - PRI (Priority):进程优先级,值越小优先级越高 - NI (Nice):优先级修正值,范围-20到19

计算公式:

PRI(new) = PRI(old) + nice

实际应用:

# 查看进程优先级ps -l# 输出示例:F UID   PID  PPID PRI  NI    SZ  STIME TTY      TIME CMD0 1000 1234 1233  80   0   1024 10:00 pts/0 00:00:01 bash

调整优先级:

# 方法1:top命令top → 按'r' → 输入PID → 输入nice值# 方法2:renice命令renice -n 5 -p 1234  # 将PID 1234的nice值改为5# 方法3:启动时设置nice -n 10 ./my_program  # 以nice=10启动程序

编程接口:

#include// 获取优先级intgetpriority(int which, int who);// 设置优先级intsetpriority(int which, int who, int prio);

5.3 进程调度相关概念

核心概念:

概念
定义
实际意义
竞争性
进程竞争CPU资源
需要优先级机制
独立性
进程间互不干扰
需要独立地址空间
并行
多CPU同时执行多进程
提高吞吐量
并发
单CPU快速切换执行多进程
提高响应速度

六、进程切换:CPU上下文管理

6.1 上下文切换的本质

设计目的:实现并发执行,让多个进程共享CPU。

切换过程:

保存当前进程上下文 → 选择下一个进程 → 加载新进程上下文 → 执行新进程

上下文内容: - CPU寄存器内容 - 程序计数器(PC) - 栈指针(SP) - 其他处理器状态

6.2 时间片轮转

机制:每个进程分配固定时间片,时间片用完强制切换。

实现:

// 时间片本质是一个计数器struct task_struct {    unsigned long time_slice;  // 剩余时间片};

6.3 Linux O(1)调度算法

设计目标:调度时间复杂度为O(1),不随进程数量增加而降低性能。

核心结构:

struct prio_array {    unsigned int nr_active;              // 活动进程数量    DECLARE_BITMAP(bitmap, MAX_PRIO+1);  // 位图:快速查找    struct list_head queue[MAX_PRIO];    // 140个优先级队列};

调度流程:

1. 从位图找到最高优先级的非空队列2. 取出队列第一个进程执行3. 时间片用完,移到过期队列4. 活动队列空后,交换active和expired指针

效率保证: - 位图查找:O(1) - 队列操作:O(1) - 指针交换:O(1)

想要了解更多内容,请阅读下列书籍,也可以关注小飞连载更多内容

最新文章

随机文章