proc pid_stat - ceragon/LinuxDoc GitHub Wiki
位于linux源码的 /fs/proc/array.c 里的 do_task_stat() 中。
static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task, int whole) {
cputime_t cutime, cstime, utime, stime;
if (lock_task_sighand(task, &flags)) {
if (whole) {
thread_group_times(task, &utime, &stime);
}
}
if (!whole) {
task_times(task, &utime, &stime);
}
seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n",
cputime_to_clock_t(utime),
cputime_to_clock_t(stime),
);
}
void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) {
struct signal_struct *sig = p->signal;
cputime_t rtime, utime, total;
// 计算线程组的整体耗时
thread_group_cputime(p, &cputime);
// 实际运行时长
rtime = nsecs_to_cputime(cputime.sum_exec_runtime);
// 总时间
total = cputime.utime + cputime.stime;
if (total) {
u64 temp = rtime;
temp *= cputime.utime;
do_div(temp, total);
// (rtime * utime) / (utime + stime)
// rtime * (utime / (utime + stime))
utime = (cputime_t)temp;
} else {
utime = rtime;
}
sig->prev_utime = utime;
sig->prev_stime = cputime_sub(rtime, sig->prev_utime);
*ut = sig->prev_utime;
*st = sig->prev_stime;
}
#define while_each_thread(g, t) while ((t = next_thread(t)) != g)
static inline struct task_struct *next_thread(const struct task_struct *p) {
// 线程组遍历
return list_entry_rcu(p->thread_group.next,
struct task_struct, thread_group);
}
void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times) {
struct signal_struct *sig = tsk->signal;
times->utime = sig->utime;
times->stime = sig->stime;
times->sum_exec_runtime = sig->sum_sched_runtime;
t = tsk;
// 将整个线程组的时间求和
do {
times->utime = times->utime + t->utime;
times->stime = times->stime + t->stime;
times->sum_exec_runtime += t->se.sum_exec_runtime;
} while_each_thread(tsk, t);
}
void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) {
cputime_t rtime, utime = p->utime, total = cputime_add(utime, p->stime);
rtime = nsecs_to_cputime(p->se.sum_exec_runtime);
if (total) {
u64 temp = rtime;
temp *= utime;
do_div(temp, total);
utime = (cputime_t)temp;
}
p->prev_utime = max(p->prev_utime, utime);
p->prev_stime = max(p->prev_stime, cputime_sub(rtime, p->prev_utime));
*ut = p->prev_utime;
*st = p->prev_stime;
}