子进程计数未达预期,是sleep()问题还是逐次输出计数的问题?
问题原因结论
你的两个猜想均正确,迭代次数不足是IO操作耗时和usleep最低时长保证两个因素共同作用的结果,还有少量额外因素也会放大误差。
具体原因说明
usleep的调度特性:POSIX标准明确规定usleep()的休眠时长是最小值,系统调度器只会保证进程不会在指定时长结束前被唤醒。如果休眠结束后CPU正被其他进程占用,子进程只能等待下一个调度时间片才能继续执行,单次循环的休眠耗时总会≥10ms,上千次循环累计后误差会非常可观。printf的IO开销:标准输出默认是行缓冲模式,每次输出带\n的字符串都会触发缓冲区刷新,这个操作需要和内核交互,甚至要写入终端设备,单次开销在几微秒到几十微秒不等,累计下来会占用大量的预期运行时间。- 额外误差来源:父进程的
sleep(10)同样遵循「至少休眠指定时长」的规则,实际唤醒时间可能略晚于10秒,加上kill发送信号到子进程响应终止也有微秒级延迟,也会小幅压缩子进程的有效运行窗口。
验证方法
你可以通过两个简单测试验证结论:
- 注释掉子进程中的
printf语句后重新运行,iter最大值会明显升高,更接近1000的预期值 - 把
usleep的参数调整为100000(即每次休眠100ms),你会发现迭代次数和预期的100次误差比例会显著降低,因为固定IO开销占单次循环总时长的比例大幅下降
代码笔误修正
你提供的代码存在一处笔误,父进程末尾的print("Everything has finished");应为printf("Everything has finished");,该问题不影响本次计数结果。修正后的参考代码如下(补充了必要的头文件):
#include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> int main() { int iter=0, forkedProcess; forkedProcess = fork(); if (forkedProcess == 0) { while (1) { iter++; printf("Count for process: child is %d\n", iter); /* sleep for 1/100 of a second */ usleep(10000); } } else { printf("Process sleeping for 10 seconds: Parent\n"); sleep(10); kill(forkedProcess, SIGTERM); printf("Process killed: child. Waiting for it...\n"); wait(NULL); printf("Everything has finished"); } }
内容的提问来源于stack exchange,提问作者StaticStacksStack
相关产品推荐
相关产品推荐

