proc pid_stat - ceragon/LinuxDoc GitHub Wiki

proc pid stat

位于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),
    );
}

thread_group_times

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);
}

task_times

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;
}
⚠️ **GitHub.com Fallback** ⚠️