交互式C Shell子进程CPU时间输出异常(负数/零值)求助
解决子进程CPU时间统计异常问题
问题原因分析
tms结构误用:- 你在子进程中调用
times(&child_time_start),但fork后父子进程内存空间完全独立,父进程中的child_time_start从未被赋值,是随机垃圾值,导致计算差值时出现负数或异常大数。 struct tms里的tms_cutime和tms_cstime字段,本身就是父进程所有已终止子进程累计的用户态/系统态CPU时间,不需要手动计算起止差值。
- 你在子进程中调用
clock()的局限:clock()仅统计调用进程自身的CPU时间,父进程在wait期间几乎不消耗CPU,所以返回值始终接近0,无法统计子进程时间。
修正方案
- 删除子进程中的
times调用,父进程在wait后调用times,直接读取tms_cutime和tms_cstime。 - 由于这两个字段是累计值,循环执行多个子进程时,需要记录上一次的累计值,用当前值减去上一次值,得到单个子进程的时间。
- 修复变量声明错误:
clk_tk需正确声明为clock_t类型。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/times.h> int main(void) { struct tms prev_tms, curr_tms; clock_t clk_tk = sysconf(_SC_CLK_TCK); // 初始化累计时间,避免第一次计算出错 times(&prev_tms); while (1) { pid_t pid = fork(); // 子进程 if (pid == 0) { execlp("/bin/ls", "ls", (char *)0); perror("execlp failed"); exit(1); } // 父进程 else if (pid > 0) { wait(NULL); times(&curr_tms); // 计算当前子进程的CPU时间:当前累计值 - 上一次累计值 double child_user_time = (double)(curr_tms.tms_cutime - prev_tms.tms_cutime) / clk_tk; double child_sys_time = (double)(curr_tms.tms_cstime - prev_tms.tms_cstime) / clk_tk; printf("子进程用户CPU时间:%.6f s,系统CPU时间:%.6f s\n", child_user_time, child_sys_time); // 更新累计时间,为下一次计算做准备 prev_tms = curr_tms; } // fork失败处理 else { perror("fork failed"); exit(1); } } return 0; }
关键说明
sysconf(_SC_CLK_TCK)获取系统时钟tick数,用于将时钟周期转换为秒。tms_cutime/tms_cstime仅统计已终止子进程的时间,必须在wait之后读取。- 记录每次的
prev_tms,确保每次循环只统计当前子进程的时间,而非所有子进程的累计值。
内容的提问来源于stack exchange,提问作者yolopoi
相关产品推荐
相关产品推荐

