学嵌入式和Linux应用编程|学习日记Day26:Linux进程完整学习笔记
|
今日主题:Linux 多任务之进程,理解进程概念、状态、命令、fork 与 exec 函数,搞懂父子进程、僵尸进程、孤儿进程。 |
前言
Linux 实现多任务依靠多进程、多线程。进程是操作系统资源分配的最小单元,嵌入式 Linux 开发中,进程是必须吃透的基础,今天完整梳理进程整套知识点。
一、进程基础概念
1. 程序与进程的区别
|
对比项 |
程序 |
进程 |
|
存储位置 |
存放在硬盘空间 |
加载到内存运行 |
|
属性 |
静态,一堆指令集合 |
动态,拥有完整生命周期 |
|
资源占用 |
不占用内存 CPU |
占用内存、CPU 资源 |
|
关系 |
一个程序可以产生多个进程;一个进程内部也可以执行多个程序 |
程序运行之后才生成进程 |
简单理解:gcc main.c -o a.out得到的a.out是程序;执行./a.out跑起来之后,就是进程。
2. 进程的创建
进程启动时,操作系统会给它分配0~4G 虚拟内存空间。
进程是操作系统资源分配的最小单元。
3. CPU 调度:宏观并行,微观串行
单核 CPU,看上去多个任务同时跑(并发),实际 CPU 在快速切换任务。
- 并行:多个任务真正同时执行,需要多核 CPU。
- 并发:单核 CPU 时间片轮转,快速切换,看起来同时运行。
CPU 常见调度算法
- 时间片轮转算法
- 先来先服务、后来后服务算法
- 高优先级优先执行算法
- 短作业优先算法
4. 进程三态基础模型

- 就绪态:一切准备完成,只差 CPU 时间片
- 运行态:正在被 CPU 执行
- 阻塞态:等待 IO 资源,例如getchar()、fgets()等待用户输入
二、Linux 真实进程 7 种状态
Linux 内核把进程细化成 7 种状态:
|
状态标识 |
状态名称 |
说明 |
|
R |
运行态 |
用户态 / 内核态,正在被 CPU 调度执行 |
|
S |
就绪态 |
具备运行条件,等待 CPU 分配时间片 |
|
S |
可中断睡眠态 |
也叫睡眠态,阻塞等待资源,可以被信号唤醒 |
|
D |
不可唤醒等待态 |
不会被 CPU 信号打断,等待硬件 IO 完成 |
|
T |
暂停态 |
进程被暂停执行 |
|
Z |
僵尸态 |
进程已经执行结束,但资源没有被父进程回收 |
|
X |
结束态 |
进程结束,资源完全回收 |
|
思维导图简单理解: |
三、进程的消亡
进程消亡分为两步:
- 进程退出:程序执行完毕,进程结束
- 进程回收:父进程回收子进程占用的内存资源,没有回收就变成僵尸进程
四、Linux 进程常用命令
|
命令 |
作用 |
常用示例 |
|
ps -aux |
查看全部进程 PID、状态、CPU / 内存占用 |
ps -aux | grep a.out过滤自己程序 |
|
ps -ef |
查看 PID 与 PPID(父进程 ID) |
PPID 就是父进程 ID |
|
top |
动态实时监控进程、CPU、内存负载 |
|
|
pstree |
树形展示进程父子族谱关系 |
pstree -sp PID查看指定进程父子链 |
|
kill |
给进程发送信号 |
kill -9 PID强制结束进程;kill -l查看全部信号 |
|
jobs |
查看当前终端后台进程编号 |
|
|
fg 编号 |
把后台进程调到前台运行 |
|
进程状态字符补充:
|
五、进程相关 C 语言系统函数
1. fork () 创建子进程
|
c |
功能:创建子进程。原来进程叫父进程,新生成叫子进程。
|
底层逻辑:子进程完整拷贝父进程 0‑4G 用户空间;内核 PCB 部分部分拷贝;PID 不拷贝,PPID 修改为父进程 ID。 |
返回值规则
- pid > 0:父进程返回,返回值是子进程 PID
- pid = 0:子进程内部返回 0
- -1:创建失败
配套函数:
- getpid() 获取自己进程 ID
- getppid() 获取父进程 ID
⚠️重要注意点
- 父子进程用户空间互相独立,变量互不干扰
- 进程之间不能直接通信,要通信必须借助内核 IPC 机制
2. 进程退出函数
进程结束三种途径:
- main 函数return返回
- exit()/_Exit()系统函数主动退出
- 收到 kill 信号强制结束
|
c |
status:进程结束状态,0 代表正常退出,非 0 代表异常退出。
3. 僵尸进程 & 孤儿进程
- 僵尸进程 (Zombie):子进程已经结束,父进程没有回收它资源,残留 PCB。
解决办法:
①父进程调用wait() / waitpid()回收子进程
②让子进程变成孤儿进程,由系统进程自动回收
- 孤儿进程:父进程提前结束,子进程还在运行;子进程被系统进程收养,结束后自动回收资源,不会产生僵尸。
4. exec 函数簇
|
作用:在当前进程内部,加载并运行另外一个外部可执行程序,替换当前进程文本段,不会创建新 PID。 |
exec 家族函数记忆口诀:
- l → list 参数列表形式传参
- v → vector 指针数组形式传参
- p → 使用 PATH 环境变量自动搜索程序路径
- e → 可以自定义传入环境变量
|
函数原型 |
特点 |
|
execl(path,arg...,NULL) |
路径 + 列表传参,NULL 做结尾标记 |
|
execlp(file,arg...,NULL) |
依靠 PATH 找程序,列表传参 |
|
execv(path,argv[]) |
路径 + 字符串指针数组传参 |
|
execvp(file,argv[]) |
PATH 查找,指针数组传参 |
|
execle / execve |
额外支持自定义环境变量 |
|
返回值:只有出错才返回‑1,执行成功当前程序直接被替换,后续代码不再运行。 |
今日学习小结
- 程序静态存硬盘,进程动态跑内存;一个程序可以生成多个进程。
- 进程基础三态:就绪‑运行‑阻塞;Linux 细化 7 种状态,重点区分僵尸、孤儿。
- fork()拷贝生成子进程,父子空间隔离;exec替换进程运行别的程序。
- 命令ps/top/pstree/kill日常调试进程必用。
僵尸进程根源:子进程退出父进程没有回收;孤儿进程父进程先退出,系统帮忙善后。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)