Linux软件编程:进程
·
目录
一、基本概念
- 进程:程序动态执行的过程,包含创建、调度、消亡等阶段
- 程序:存放在外存中的一段数据集合(静态)
二、进程创建
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
-
WIFEXITED(wstatus) :测试进程是否正常结束WEXITSTATUS(wstatus) :获得进程退出的值WIFSIGNALED(wstatus) :测试进程是否被杀死WTERMSIG(wstatus) :获得杀死该进程的信号编号
注意:
- wait具有阻塞等待功能,等到有子进程结束才会回收子进程继续向下执行
- wait可以实现父子进程任务的同步
2.waitpid
- 可指定回收特定子进程(功能更灵活)
-
原型: pid_t waitpid(pid_t pid, int *wstatus, int options);功能:回收指定的子进程空间参数:pid:要回收的进程的 PID ( -1 表示回收任意子进程)wstatus: 存放子进程结束状态空间首地址options:0 阻塞回收WNOHANG 非阻塞回收返回值:成功返回回收到的子进程 PID失败返回 -1指定的子进程空间没结束,返回 0waitpid(-1, NULL, 0) 等价于 wait(NULL)注意:
- waitpid可以非阻塞回收子进程空间
- waitpid可以回收指定子进程空间
六、进程消亡
1.孤儿进程
- 产生:父进程先结束,子进程成为孤儿进程
- 处理:被
init进程收养
2.僵尸进程
- 是每个进程结束必然会经历的阶段
- 产生原因:子进程结束后,父进程未回收其空间,导致空间被占用
3.如何避免产生僵尸进程?
父进程先结束,子进程会成为孤儿进程,孤儿进程被 init 进程收养,子进程再结束, init进程回收进程空间 子进程结束,父进程回收子进程空间,避免产生僵尸进程
七、exec函数族
1. exec函数族
- 利用进程空间执行另一份代码
- exec常搭配fork使用,fork负责创建新的子进程,exec负责让子进程执行自己的代码
extern char **environ;int execl(const char *path, const char *arg, .../* (char *) NULL */);int execlp(const char *file, const char *arg, .../* (char *) NULL */);int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp [] */);int execv(const char *path, char *const argv [] );int execvp(const char *file, char *const argv [] );int execvpe(const char *file, char *const argv [] ,char *const envp [] );l: 参数以列表的形式传递p: 在系统变量 PATH 对应的目录下查找文件v: 参数以指针数组的形式传递e: 执行新代码是更新环境变量
2. 主函数传参
1. 主函数形式
void main(void);int main(void);int main(int argc, const char *argv [] );int main(int argc, const char **argv);argc: 传入参数的个数argv: 存放每一个传入参数指针的数组名argv [ 0 ] = "./a.out"argv [ 1 ] = "hello"argv [ 2 ] = "world"argv [ 3 ] = "how"argv [ ... ] = ...argv [ argc ] = ...
3. system函数
原型: int system(const char *command);功能: 运行command 命令参数: command:shell命令字符串首地址返回值: 成功返回0失败返回 -1
更多推荐



所有评论(0)