C高级:Linux进程基础学习记录
Linux 进程管理详解
在操作系统中,进程(Process)是程序的一次动态执行过程,也是系统进行资源分配和调度的基本单位。与静态的程序代码不同,进程包含了程序代码、当前活动(如程序计数器的值)、处理器寄存器的状态、堆栈数据以及分配给它的系统资源(如打开的文件、内存空间等)。简而言之,进程是一个“正在运行中的程序实例”。以下是我在职坐标的学习记录:
1. 查看所有进程详细信息的指令
在 Linux 系统中,最常用的查看进程信息的命令是 ps。要获取系统中所有进程的详细信息,通常使用以下两种格式:
ps aux:这是 BSD 风格的命令,常用于查看系统中所有用户的进程,并显示详细的资源占用情况。ps -ef:这是 System V 风格的命令,同样用于列出所有进程,并展示完整的父子进程关系。
2. 常见头部字段解释
执行上述 ps 命令后,输出结果通常包含多个列,以下是几个核心字段的含义:
- USER:启动该进程的用户账户名称。
- PID:进程 ID(Process ID),是操作系统为每个进程分配的唯一标识符。
- PPID:父进程 ID(Parent Process ID),即创建该进程的父进程的 PID。
- %CPU / %MEM:分别表示该进程占用的 CPU 时间百分比和物理内存百分比。
- STAT:进程当前的状态(如 R 表示运行,S 表示休眠,Z 表示僵尸进程等)。
- VSZ:虚拟内存占用大小
- RSS:物理内存占用大小
- TTY:终端编号
- START:开始时间
- END:结束时间
- COMMAND:启动该进程的命令名称及其参数。
3. 任务控制与进程切换
jobs 命令的功能
jobs 命令用于列出当前 Shell 会话中正在后台运行或已暂停的任务及其状态。它仅对当前终端会话有效。
前后台进程切换
Linux 提供了灵活的机制来在后台和前台之间切换进程:
- 后台运行 (
&):在命令末尾加上&符号,可以让程序在后台执行,从而释放当前终端供其他操作使用。例如:command &。 - 暂停进程:在前台运行的进程中按下
Ctrl + Z,可以将其暂停(挂起)并放入后台。 - 后台恢复 (
bg):使用bg %job_number可以让一个被暂停的后台任务继续在后台运行。 - 前台恢复 (
fg):使用fg %job_number可以将后台任务(无论是运行中还是暂停状态)调回前台继续执行。
杀死进程 (kill 命令)
当需要强制终止一个进程时,可以使用 kill 命令。它通过向进程发送信号(Signal)来实现控制:
- 常规终止:
kill PID(默认发送 SIGTERM 信号,允许进程进行清理后退出)。 - 强制终止:
kill -9 PID(发送 SIGKILL 信号,强制立即终止进程,进程无法捕获或忽略该信号)。
4. 进程三态图
进程在生命周期中会在以下三种基本状态之间转换:
- 运行态(Running):进程正在 CPU 上执行指令。
- 就绪态(Ready):进程已具备运行条件,正在等待 CPU 的调度分配。
- 阻塞态(Blocked / Waiting):进程因等待某个事件(如 I/O 操作完成、等待信号量等)而暂时无法执行。
状态转换逻辑:
- 就绪态 → 运行态:被操作系统调度程序选中,分配 CPU。
- 运行态 → 就绪态:时间片用完或被更高优先级的进程抢占。
- 运行态 → 阻塞态:主动请求 I/O 或等待某事件。
- 阻塞态 → 就绪态:等待的事件已完成,重新具备运行条件。
5. 核心系统调用
-
在 C 语言中,Linux 通过以下系统调用来实现进程的创建、执行与同步。
5.1
fork():创建新进程pid_t fork(void);-
函数作用:
通过复制当前进程(父进程)创建一个几乎完全相同的新进程(子进程)。子进程拥有独立的 PID、独立的内存空间(写时复制 COW),但继承了父进程的文件描述符、环境变量等。 -
参数:无。
-
返回值(关键):
- 父进程中:返回 子进程的 PID(大于 0)。
- 子进程中:返回 0。
- 失败时:返回 -1,并设置
errno。
-
代码逻辑示例:
pid_t pid = fork(); if (pid < 0) { /* 错误处理 */ } else if (pid == 0) { /* 子进程执行逻辑 */ } else { /* 父进程执行逻辑 */ }
5.2
execlp():执行新程序int execlp(const char *file, const char *arg, ... /* (char *) NULL */);-
函数作用:
用参数指定的新程序替换当前进程的映像。调用成功后,原进程代码不再执行,而是从新程序的main开始;若失败则返回 -1。 -
参数详解:
- file:要执行的可执行文件名。
p后缀表示会在环境变量PATH中自动搜索路径。 - arg:新程序的参数列表。第一个参数必须是文件名本身(即
argv[0])。 - ...:后续参数,必须以 (char *)NULL 结尾。
- file:要执行的可执行文件名。
-
示例:
// 相当于执行: ls -l /home execlp("ls", "ls", "-l", "/home", (char *)NULL);
5.3
wait():回收子进程pid_t wait(int *status);- 函数作用:
父进程调用后会阻塞,直到任意一个子进程终止。用于获取子进程退出状态并释放其内核资源,防止僵尸进程。 - 参数详解:
status:若非NULL,内核会将子进程的退出状态写入该整型变量。- 需使用宏解析:
WIFEXITED(status)判断是否正常退出,WEXITSTATUS(status)获取退出码。 - 若
WIFSIGNALED(status)为真,则子进程被信号杀死,用WTERMSIG(status)获取信号值。
- 需使用宏解析:
- 返回值:
- 成功:终止子进程的 PID。
- 失败:-1(如没有子进程时返回
ECHILD)。
5.4
waitpid():精确等待pid_t waitpid(pid_t pid, int *status, int options);- 函数作用:
wait()的增强版,支持等待指定子进程,且支持非阻塞模式。 - 参数详解:
- pid:
> 0:等待指定 PID 的子进程。-1:等待任意子进程(等同于wait())。0:等待同进程组的任意子进程。< -1:等待指定进程组的任意子进程。
- status:同
wait(),用于存储退出状态。 - options:
0:阻塞等待(同wait())。- WNOHANG:非阻塞。若指定子进程未结束,立即返回 0,不挂起父进程。
- pid:
- 返回值:
> 0:终止子进程的 PID。0:使用了WNOHANG且子进程尚未结束。-1:出错。
5.5
system():Shell 命令执行int system(const char *command);- 函数作用:
高级库函数,内部封装了fork()+execl("/bin/sh", ...)+waitpid()。用于在 Shell 中执行字符串命令。 - 参数详解:
- command:Shell 命令字符串(如
"ls -l | grep txt")。 - 若为 NULL,用于检测系统是否存在 Shell。
- command:Shell 命令字符串(如
- 返回值:
command为 NULL:非 0 表示有 Shell 可用。- 执行成功:返回命令的退出状态(需
WEXITSTATUS解析)。 - 执行失败/Shell 不存在:返回 -1 或 127。
-
- 安全警告:
严禁在 Set-UID 程序或不可信输入中使用system(),极易导致命令注入漏洞。生产环境应优先使用fork()+exec家族。
- 安全警告:
核心函数对比总结
函数 核心作用 是否阻塞 关键特性 fork 复制进程 否 一次调用,两次返回 execlp 替换进程映像 否 成功不返回,失败才返回 wait 回收任意子进程 是 防止僵尸,获取退出码 waitpid 回收指定子进程 可控 支持 WNOHANG非阻塞system 执行 Shell 命令 是 方便但开销大,有安全风险 -
浙公网安备 33010602011771号