Linux软件编程:进程
目录
一、基本概念
二、进程创建
1. 进程空间分布
2. 虚拟地址与物理地址
3. 多进程存储与调度
三、进程相关命令
1. top
2. ps -ef
3. ps -aux
4. 后台执行进程任务
5. jobs
6. fg
7. nice/renice
8. kill/killall
四、进程状态
五、进程相关函数接口
1.fork:创建子进程
2.getpid/getppid
3.exit与_exit
4.进程回收
1.wait
2.waitpid
六、进程消亡
1.孤儿进程
2.僵尸进程:
3.如何避免产生僵尸进程?
一、基本概念
- 进程:程序动态执行的过程,包含创建、调度、消亡等阶段
- 程序:存放在外存中的一段数据集合(静态)
二、进程创建
1. 进程空间分布
操作系统为每个运行的进程开辟 0-4G 虚拟内存空间,分为:
- 内核空间:不允许用户访问
- 用户空间:
- 文本段:存放代码和指令
- 数据段:包含字符串常量、已初始化 / 未初始化的全局变量 / 静态变量(编译时开辟空间,程序结束回收,未初始化值为 0)
数据区存放数据特点:
- 未经初始化值为0值
- 编译时开辟空间
- 程序结束时回收空间
- 系统数据段:
- 堆区:通过
malloc
申请、free
释放(需避免内存泄露)
堆区存放数据特点:
- malloc申请堆区空间
- free释放堆区空间
- 注意:避免产生内存泄露
- 栈区:存放局部变量、函数运行数据(未初始化值为随机值,超出作用域自动回收)
栈区存放数据特点:
- 未经初始化值为随机值
- 执行到变量定义开辟内存空间
- 超过变量作用域回收变量空间
2. 虚拟地址与物理地址
- 虚拟地址:用户可见的地址,代表用户可寻址范围
- 物理地址:内存存放数据的实际硬件地址
- MMU(内存映射单元):负责虚拟地址与物理地址的映射
-
3. 多进程存储与调度
- 存储特点:多个进程物理地址独立(空间独立),但共享虚拟内存空间
-
- 调度算法:
- 先来先执行
- 高优先级调度
- 时间片轮转调度
- 调度本质:宏观并行(看似同时执行),微观串行(CPU 在多个任务间高速切换)
- 宏观分析:一个CPU同时执行多个进程任务微观分析:一个CPU在多个任务中高速切换保障多任务执行
三、进程相关命令
命令 | 功能 | 关键信息 | |
---|---|---|---|
top | 动态查看进程信息(按 CPU、内存占用率) | 显示 PID(进程 ID)、USER(创建者)、PR/NI(优先级)、% CPU、% MEM 等,q 退出 | |
ps -ef | 查看某一时刻所有进程信息 | 显示 UID(创建用户)、PID、PPID(父进程 ID)、CMD(进程命令);`ps -ef | grep 进程名 ` 可查找特定进程 |
ps -aux | 查看某一时刻所有进程信息 | 显示 USER、PID、% CPU、% MEM、STAT(状态)等 | |
./a.out & | 后台执行进程 | 进程在后台运行 | |
jobs | 查看终端后台进程任务 | 显示后台进程编号 | |
fg 编号 | 将后台进程放到前台执行 | 需通过jobs 获取进程编号 | |
nice/renice | 改变进程优先级 | 优先级范围 - 20~20(数字越小优先级越高);nice -n 优先级 进程名 /renice -n 优先级 进程PID | |
kill/killall | 杀死进程 | kill -编号 进程PID /killall -编号 进程名 ;kill -9 PID 强制终止 |
1. top
示例:top功能:根据CPU占用率和内存占用率查看当前所有进程的信息PID:唯一区分进程的ID号USER:创建者PR NI:优先级VIRTRESSHR:资源占用S:状态%CPU:CPU占用率%MEM:内存占用率TIME+:运行的时长COMMAND:进程命令q退出
2. ps -ef
示例:ps -ef功能:查看该时刻的所有进程信息UID:创建进程的用户PID:进程的ID号PPID:父进程的ID号CSTIMETTY:进程依赖的终端TIMECMDps -ef | grep 进程名查找与进程名对应的进程信息
3. ps -aux
示例:ps -aux功能:查看该时刻的所有进程信息USERPID%CPU%MEMVSZRSSTTYSTAT:进程的状态START TIMECOMMAND
4. 后台执行进程任务
示例:./a.out &功能:后台执行a.out进程
5. jobs
示例:jobs功能:查看终端下所有的后台进程任务
6. fg
示例:fg 编号(通过jobs查看)功能:后台执行的任务放到前台执行
7. nice/renice
示例:nice -n 优先级编号 进程名renice -n 优先级编号 进程PID功能:改变进程的优先级优先级范围:-20 - 20数字越小优先级越高
8. kill/killall
示例:kill -编号 进程PIDkillall -编号 进程名功能:杀死进程任务kill -9 PID
四、进程状态
状态标识 | 进程状态及含义 |
---|---|
R | 就绪态 / 运行态(位于 CPU 调度队列中) |
S | 可唤醒等待态(等待资源,可被打断,资源到来后加入调度队列) |
D | 不可唤醒等待态(等待资源,不可被打断,资源到来后加入调度队列) |
T | 停止态(用户人为暂停) |
Z | 僵尸态(进程结束,空间未回收) |
X | 结束态(进程结束,空间已回收) |
五、进程相关函数接口
1.fork
:创建子进程
- 功能:父进程调用后生成子进程,子进程拷贝父进程的文本段、数据段、系统数据段
- 返回值:父进程返回子进程 PID,子进程返回 0,出错返回 - 1
- 特点:父子进程空间独立,变量 / 数据互不影响,PID 不同
注意:
- 子进程拷贝父进程文本段、数据段、系统数据段
- 父进程与子进程空间独立,同一份代码中的变量和数据都会在父子进程中各有一份,父子进程
- 修改自己空间的数据不会影响对方的空间
- 进程的PID不一样
- fork的返回值不一样,父进程中返回子进程的PID,子进程中返回0
- PID:一定是 > 0
2.getpid
/getppid
getpid()
:原型:pid_t getpid(void); 获取当前进程 PIDgetppid()
:原型:pid_t getppid(void); 获取当前进程的父进程 PID
3.exit
与_exit
- 原型:void exit(int status);
- 功能: 结束进程任务并返回进程结束状态
- 参数: status:进程结束状态的值
- 原型:void _exit(int status);
- 功能: 结束进程任务并返回进程结束状态
- 参数: status:进程结束状态的值
注意:
- 在主函数中调用exit和return功能保持一致
- return在函数内部将结束该函数
- exit在函数内部会将进程结束
- exit会在结束前刷新缓存区
- _exit不会刷新缓存区
4.进程回收
1.wait
- 原型:pid_t wait(int *wstatus);功能: 回收子进程空间参数: wstatus:存放子进程结束状态空间的首地址返回值: 成功返回回收到的子进程的PID ;失败返回-1
注意:wait具有阻塞等待功能,等到有子进程结束才会回收子进程继续向下执行
2.waitpid
- 可指定回收特定子进程(功能更灵活)
六、进程消亡
1.孤儿进程
- 产生:父进程先结束,子进程成为孤儿进程
- 处理:被
init
进程收养
2.僵尸进程:
- 是每个进程结束必然会经历的阶段
- 产生原因:子进程结束后,父进程未回收其空间,导致空间被占用
3.如何避免产生僵尸进程?
父进程先结束,子进程会成为孤儿进程,孤儿进程被init进程收养,子进程再结束,init进程回收进程空间 子进程结束,父进程回收子进程空间,避免产生僵尸进程