You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

交互式C Shell子进程CPU时间输出异常(负数/零值)求助

解决子进程CPU时间统计异常问题

问题原因分析

  1. tms结构误用:

    • 你在子进程中调用times(&child_time_start),但fork后父子进程内存空间完全独立,父进程中的child_time_start从未被赋值,是随机垃圾值,导致计算差值时出现负数或异常大数。
    • struct tms里的tms_cutime和tms_cstime字段,本身就是父进程所有已终止子进程累计的用户态/系统态CPU时间,不需要手动计算起止差值。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:20:26