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

Day27 进程管理(PCB、状态、调度、原语与资源管理)

day27 进程管理(PCB、状态、调度、原语与资源管理)

进程的含义

进程是程序执行的动态过程,涉及内存资源分配和CPU调度。其核心组件与特性如下:

  • PCB(Process Control Block):操作系统内核中的结构体(如Linux的task_struct),存储进程所有状态信息,包括:

    • PID(进程标识符):唯一身份标识
    • 当前工作路径(通过chdir设置,pwd查看)
    • 文件描述符(fd)列表及打开的文件信息
    • 信号处理设置(用于异步I/O)
    • 用户ID/组ID
    • 资源上限(通过ulimit -a查看,例如栈大小8MB、打开文件数1024)
  • 资源管理:进程占用CPU、内存(RAM)、闪存(Flash)、固态硬盘(SSD)等物理资源,通过虚拟地址映射(MMU管理)隔离物理内存,每页4KB。

  • 内存空间划分

    • 0-3GB:用户空间(包含代码段、数据段、堆、栈)
    • 3-4GB:内核空间(共享)
    • 虚拟地址优势:提供隔离性和权限控制

进程和程序的区别

特性程序进程
本质静态实体(存储在硬盘的代码和数据集合)动态实体(程序执行的完整过程)
生命周期永久存在暂时存在(创建→调度→消亡)
状态变化无状态变化有状态变化(就绪/运行/阻塞等)
并发性无并发可并发执行
资源竞争不竞争资源进程间竞争CPU、内存等资源
实例关系一个程序可运行多次生成多个进程一个进程可运行一个或多个程序

内存布局示例

.c 源文件 → gcc 编译 → a.out 可执行文件 (ELF格式) → 进程(PID)|├─ 虚拟地址空间 (0-3GB)│   ├─ 代码段 (只读,存放指令)│   ├─ 数据段 (全局/静态变量,读写)│   ├─ 堆 (malloc/free,<3GB)│   ├─ 共享库 (如libc.so,通过mmap映射)│   └─ 栈 (局部变量/参数,8MB)└─ 内核空间 (3-4GB)
  • 地址空间说明
    • 32位系统:4GB虚拟地址空间(2^32)
    • 64位系统:256TB虚拟地址空间(2^48)

进程的作用与并发并行区别

  • 核心作用:实现任务并发执行,提升系统资源利用率
  • 并发 vs 并行
    • 并发:单CPU上快速切换执行多个任务(微观串行,宏观并行)
    • 并行:多CPU同时执行多个任务(真正同时运行)

并发执行示例

while (1) {          // 主循环while (1) {      // 子任务循环(如接收控制指令)// 处理上下左右方向}// 发送视频流
}

说明:通过进程/线程切换实现多任务交替执行,避免单任务阻塞

进程的状态

基本状态转换

就绪态 → (CPU调度) → 运行态 → (条件不满足) → 阻塞态 → (条件满足) → 就绪态

Linux进程状态标识(ps aux输出)

状态符含义说明
R运行/就绪态正在CPU执行或等待调度
S可中断睡眠态等待事件(可被信号唤醒)
D不可中断睡眠态等待I/O完成(不可唤醒)
T暂停态被信号停止(如SIGSTOP)
Z僵尸态进程已终止但资源未回收
(无)结束态资源完全回收

进程的调度与上下文切换

  • 调度核心:内核通过调度算法分配CPU时间片
  • 上下文切换:保存/恢复进程状态(寄存器、PC指针等),涉及:
    • 程序计数器(EIP)
    • 栈指针
    • 通用寄存器

调度算法

算法说明
先来先服务(FCFS)按到达顺序执行
短任务优先(SJF)优先执行预计运行时间短的任务
多级反馈队列分优先级队列,动态调整

关键特性:宏观上多进程并行,微观上CPU串行执行

查询进程相关命令

1. ps aux

  • 功能:查看进程实时状态
  • 关键字段
    • STAT:进程状态(R/S/D/T/Z)
    • PID:进程ID
    • PPID:父进程ID
  • 安装树状工具sudo apt install pstree

2. top

  • 功能:动态监控CPU/内存占用率最高的进程

3. kill / killall

  • 发送信号
    kill -2 <PID>     # 发送SIGINT(默认终止进程)
    kill -9 <PID>     # 发送SIGKILL(强制终止)
    killall -9 a.out  # 终止所有a.out进程
    

进程原语

1. fork()

  • 功能:创建子进程(父进程的副本)
  • 特性
    • 一次调用,两次返回(父进程返回子PID>0,子进程返回0)
    • 子进程复制父进程0-3GB空间及PCB,但PID不同
    • 写时复制(COW)机制:修改时才复制内存
    • 执行顺序不确定(需IPC同步)

代码示例与注释

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>int main(int argc, char *argv[])
{pid_t ret = fork(); // 创建子进程,返回两次if(ret > 0) // 父进程分支(ret = 子进程PID){while(1) // 父进程无限循环{printf("father,发视频....\n");sleep(1); // 暂停1秒控制输出频率}}else if(0 == ret) // 子进程分支(ret = 0){while(1) // 子进程无限循环{printf("child,接收控制....\n");sleep(1);}}else // fork失败{perror("fork err\n");return 1;}return 0;
}

理想运行结果
father,发视频…
child,接收控制…
father,发视频…
child,接收控制…
(交替输出,顺序取决于调度)

变量隔离验证

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int a = 20; // 全局变量
int main()
{pid_t ret = fork();if(ret > 0) // 父进程{sleep(3); // 确保子进程先修改printf("father ,a is %d\n", a); // 输出20}else if(0 == ret) // 子进程{a += 10; // 修改副本printf("child ,a is %d\n", a); // 输出30}printf("a is %d\n", a); // 父进程输出20,子进程输出30return 0;
}

理想运行结果
child ,a is 30
a is 30
father ,a is 20
a is 20

2. getpid()getppid()

  • 功能
    • getpid():获取当前进程PID
    • getppid():获取父进程PID

代码示例

#include <stdio.h>
#include <unistd.h>int main()
{pid_t ret = fork();if(ret > 0) // 父进程{sleep(3);printf("father ,pid:%d ppid:%d\n", getpid(), getppid());}else if(0 == ret) // 子进程{printf("child ,pid:%d ppid:%d\n", getpid(), getppid());}printf("pid:%d ppid:%d\n", getpid(), getppid());return 0;
}

理想运行结果
child ,pid:26205 ppid:26204
pid:26205 ppid:26204
father ,pid:26204 ppid:3199
pid:26204 ppid:3199
(3199为终端父进程ID)

3. 多重fork()分析

#include <stdio.h>
#include <unistd.h>int main()
{fork() && fork() || fork(); // 逻辑运算符触发5个进程printf("pid:%d\n", getpid());return 0;
}

进程关系
1个父进程 → 生成4个子进程(含1个孙进程)
理想运行结果
pid:1001
pid:1002
pid:1003
pid:1004
pid:1005
(共5行输出,PID顺序不定)

父子进程的关系

  • 核心关系:子进程是父进程的副本(共享代码段,数据段写时复制)
  • 关键区别
    1. fork()返回值不同(父进程>0,子进程=0)
    2. PID/PPID不同
    3. 资源计数器重置(如文件描述符)
  • 执行起点:子进程从fork()后开始执行
  • 典型场景
    • 网络服务:父子进程执行相同代码
    • 程序替换:fork() + exec()执行新程序

进程的终止

8种终止情况

类型方式说明
正常终止1. main()return返回退出状态
2. exit()刷新缓冲区,调用atexit注册的清理函数
3. _exit()/_Exit()不刷新缓冲区,直接终止
4. 主线程return仅终止当前线程
5. pthread_exit()线程级退出
异常终止6. abort()发送SIGABRT信号
7. kill信号kill -9 PID
8. pthread_cancel()取消最后一个线程

exit() vs _exit()

#include <stdio.h>
#include <unistd.h>int main()
{printf("hello"); // 无换行符,缓冲区未刷新// exit(0);     // 会刷新缓冲区 → 输出"hello"_exit(0);        // 不刷新缓冲区 → 无输出return 0;
}

关键区别

  • exit(0):先刷新I/O缓冲区,再执行清理函数,最后调用_exit()
  • _exit(0):立即终止,不处理缓冲区和清理函数
    理想结果
  • exit(0)时输出hello
  • _exit(0)时无输出

僵尸进程和孤儿进程

僵尸进程

  • 成因:子进程终止但父进程未回收资源(wait()未调用)

  • 验证代码

    int main()
    {pid_t ret = fork();if(ret > 0) // 父进程{while(1) { printf("father,发视频....pid:%d ppid:%d\n", getpid(), getppid());sleep(1);}}else // 子进程{sleep(3); exit(0); // 子进程终止,但父进程未回收 → 僵尸}return 0;
    }
    

    现象ps aux中子进程状态为Z,资源未释放

孤儿进程

  • 成因:父进程先于子进程终止,子进程被init接管
  • 验证代码
    int main()
    {pid_t ret = fork();if(ret > 0) // 父进程{sleep(3); exit(0); // 父进程提前终止}else // 子进程{while(1) { printf("child,接收控制....pid:%d ppid:%d\n", getpid(), getppid());sleep(1);}}return 0;
    }
    

    现象:子进程PPID变为1(init进程ID)

资源回收:僵尸进程需父进程调用wait()/waitpid()回收;孤儿进程由init自动回收

http://www.dtcms.com/a/350060.html

相关文章:

  • pikachu之Over permission
  • 基于SpringBoot的宠物领养系统的设计与实现(代码+数据库+LW)
  • QML中的Connections
  • Vue 3 defineOptions 完全指南:让组件选项声明更现代化
  • vb6编绎COM DLL(ACTIVEX对象)时兼容性设置
  • bisheng 后端初始化数据(main.py > init_data.py)
  • 25072班8.25日 数据结构作业
  • 04-Maven工具介绍
  • kafka 副本集设置和理解
  • 《Spring Boot 进阶:从零到一打造自定义 @Transactional》 ——支持多数据源、动态传播行为、可插拔回滚策略
  • AI系列 - Claude 与 Qwen 模型自动补全对比:谁更胜一筹?
  • 电力系统稳定性的挑战与智能控制新范式
  • 网络与信息安全有哪些岗位:(8)安全审计员
  • C 语言:第 20 天笔记:typedef(类型重命名规则、应用场景与实战案例)
  • 黑客窃取 EDR 检测未检测到的 Windows 机密和凭证
  • 讲解计网中OSI模型及各层作用
  • 网闸和防火墙各有什么长处?
  • ValueTask 实战指南:解锁 .NET 异步编程的性能秘密
  • maui中配置安卓手机在测试环境连接网络
  • 创建Java集成开发环境
  • 车载诊断架构 --- 基于以太网做software download的疑问汇总
  • [QMT量化交易小白入门]-八十四、LSTM模型对期货市场的秒级Tick数据进行预测
  • 14.examples\01-Micropython-Basics\demo_yield.py 加强版
  • 深入浅出 ArrayList:从基础用法到底层原理的全面解析(中)
  • 深度剖析 Grok2 开源:技术原理与创新洞察
  • 奶茶品牌ESG实践:从绿色供应链到可持续竞争力
  • 离线可用的网络急救方案
  • [RK3568][Android11] Android->默认显示设置->系统->开发者选项(不用连续点击版本号)
  • FunASR基础语音识别工具包
  • 学习Python第13天