操作系统原理:实验1进程观测
(1)
文件名命名为process1.c
使用gcc process1.c -o process编译该程序
输入命令top,观察名称为process1的进程
我们总结ps aux | grep process 进程所得到的信息
| 字段 | 含义 |
|---|---|
3557 | 进程号(PID) |
35.7 | CPU 占用率:35.7% |
0.0 | 内存占用率(%MEM) |
2680 | 虚拟内存使用量(KB) |
1180 | 实际物理内存使用量(KB) |
pts/0 | 运行在终端0 |
R+ | 状态:正在运行(Running) |
20:17 | 启动时间 |
0:16 | 已使用 CPU 时间(16秒) |
CPU占用率与循环关系最密切。因为 printf 是 I/O 操作,但循环本身没有阻塞或延时,CPU会不断地执行循环体,导致 CPU使用率极高。
kill指令执行后,目标进程会被成功终止并从系统的进程列表中移除
通过上述实验我们可以知道:循环与CPU占有率关系最密切。 为了避免其负面影响,我们应在代码中引入休眠、使用事件驱动模型,在系统层面实施监控和资源限制。这个问题的本质揭示了CPU是现代操作系统中需要被精心管理和保护的、最关键的资源之一。它与内存、磁盘I/O、网络I/O等共同构成了系统性能的基石。
(2)

同理对我们process2文件进行编译
我们尝试运行该程序


以上三种情况均为同一程序运行结果。
我们可以发现结果输出顺序不确定,取决于操作系统调度。可能父进程先结束,子进程继续输出。
原因为fork() 后,父进程和子进程是独立调度的。两者并发执行,输出竞争标准输出缓冲区。输出顺序不确定,但总量大致相等(各999行)。
我们对process2改写为process21的状态
编译运行进行观察
父进程输出 999 行后退出。
子进程继续无限输出,进程仍在运行。
我们可以看到:父进程状态已消失。子进程状态为 R,PID 仍在。
原因是父进程结束后,子进程成为孤儿进程。被 init 进程(PID=1)收养,继续运行。直到手动 kill 子进程,才会停止。
我们对process2改写为process3的状态
我们对process3进行观察

我们可以观察发现两个进程都无限循环。输出交替或混乱,取决于调度。使用 top 可以看到:两个进程,CPU占用率都很高。
原因:父子进程独立调度,各自占用CPU资源。输出竞争终端,可能出现交错打印。必须手动 kill 两个进程,才能终止。
总结
1️⃣ 为什么死循环几乎不占内存,却能把 CPU 拉到 30%~40%?
while(1) printf(...)只反复写 3 字节字符串,堆栈不增长 → 内存恒定 ≈ 0 %但循环体 无阻塞,每秒可执行 上百万次系统调用;内核不断调度 → 单核 30 %~40 % 很轻松
结论:CPU 是“时间”资源,内存是“空间”资源;二者消耗逻辑不同
2️⃣ 状态 R ↔ S 反复跳变正常吗?
终端输出速度 ≈ 几千行/秒,缓冲区一满
printf就阻塞 → 进程进入 S(可中断睡眠)终端刷完缓冲区后唤醒 → 又回到 R
若把输出重定向到文件:
./a.out > log
– 文件缓冲大,阻塞次数锐减 → R 状态常驻,CPU 占用飙升到 100 %结论:S 状态不是“卡住”,而是等 I/O;观察 CPU 时请同时看 %CPU 与 STATE
3️⃣ 父进程退出后子进程为何还在?
子进程变成 孤儿进程,被 init/systemd(PID=1)收养
仍无限循环打印 → 必须手动 kill
经验:同时开两个终端,一个
./a.out,另一个ps -ef | grep a.out可看到 PPID 变为 1
4️⃣ 终端里输出“乱序/交织”怎么办?
父子进程并发写同一终端设备,缓冲区竞争
解决思路
① 各自fflush(stdout);立即刷新
② 加同步(如文件锁、信号量)——后续实验会学到
③ 把输出重定向到不同文件:./a.out > parent.log 2>&1 &/./a.out > child.log 2>&1 &
5️⃣ 如何“优雅”地让 CPU 占用趋近于 0?
| 方法 | 效果 |
|---|---|
sleep(n); | 秒级休眠,CPU 几乎 0 % |
usleep(100000); | 0.1 s 级,兼顾响应与 CPU |
| 条件等待/信号量 | 真正事件驱动(高级) |
6️⃣ 杀死进程后 ps 还能查到?
查到的其实是 grep 自身
用
ps aux | grep [p]rocess或pgrep -f process可排除 grep 行
| 现象 | 根因 | 一句话解决 |
|---|---|---|
| CPU 100 % | 死循环无阻塞 | 加 sleep() |
| 输出顺序乱 | 多进程竞争终端 | 各自重定向文件 |
| 状态老在 S | 等终端 I/O | 重定向或减小打印频率 |
| kill 后还在 | 只杀了父进程 | pkill -f 名字 或 kill -9 PID |
| 内存暴涨 | 循环里 malloc 忘 free | Valgrind 检查泄漏 |

