Linux进程与子进程用户/系统时间统计的技术疑问
APUE示例8.31时间统计代码的疑问解答
以下是基于APUE示例8.31的代码,用于统计每个传入命令的进程自身及子进程的用户态(user)/内核态(sys)时间:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/times.h> void do_cmd(int, const char *); void pr_times(clock_t, clock_t, struct tms *, struct tms *); int main (int argc, char *argv[]) { long clktck = 0; clktck=sysconf(_SC_CLK_TCK); for (int i=1; i<argc; i++) do_cmd(clktck, argv[i]); exit (0); } void do_cmd(int clktck, const char *cmd) { struct tms tmsstart, tmsend; clock_t start, end; start=times(&tmsstart); system(cmd); end = times(&tmsend); printf("command:%s\n", cmd); pr_times(clktck, end-start, &tmsstart, &tmsend); printf("\n"); } void pr_times(clock_t clktck, clock_t real, struct tms *start, struct tms *end) { printf("real:%7.2f\n", real/(double)clktck); printf("user:%7.2f\n", (end->tms_utime - start->tms_utime) / (double)clktck); // this line printf("sys:%7.2f\n", (end->tms_stime - start->tms_stime) / (double)clktck); // and this line printf("cuser:%7.2f\n", (end->tms_cutime- start->tms_cutime)/ (double)clktck); printf("csys:%7.2f\n", (end->tms_cstime- start->tms_cstime)/ (double)clktck); }
技术问询
通过system()函数执行命令的方案中,统计得到的user和sys时间是否可能大于0?若可能,触发场景是什么?还是因为命令以子进程形式执行,这两个值始终为0?
测试执行命令:
./a.out "sleep 10" "find / -name a* 1>/dev/null 2>&1" 'bash -c "for ((i=0;i<1000000;i++)); do :; done;" '
解答
user和sys时间有可能大于0,并非始终为0,原因和触发场景如下:
system()的内部实现逻辑system()的标准实现流程是:
- 父进程调用
fork()创建子进程,这一步是系统调用,会消耗父进程的内核态时间(计入sys); - 父进程调用
wait()等待子进程结束,wait()本身的系统调用开销也会算入sys时间; - 如果
system()的实现中包含用户态的处理逻辑(比如参数校验、错误处理的用户态代码),这部分会贡献user时间。
- 实际触发场景
- 当频繁执行
system()调用时,fork()和wait()的系统开销会累积,导致sys时间明显大于0; - 若传入的命令需要shell做复杂的字符串解析、变量扩展(比如带大量通配符、脚本逻辑的命令),
system()在调用shell的过程中,父进程的少量用户态前置处理也可能产生非零的user时间; - 即使是单次简单命令执行,
fork()和wait()的系统调用也会带来微小的sys时间增量(可能因时钟分辨率问题在输出中显示为0.00,但实际非零)。
简单来说,统计的user/sys时间是当前进程(即我们的程序进程)自身的耗时,和子进程的耗时无关——子进程的时间会被统计到cuser和csys字段中。只要当前进程在执行system()的过程中有用户态或内核态的操作,这两个值就可能大于0。
内容的提问来源于stack exchange,提问作者tahzibi.jafar
相关产品推荐
相关产品推荐

