1.背景介绍
proc文件系统提供了对内核参数信息,在此只介绍进程相关的参数;
proc是内核提供的一种文件系统,内核代码位置:linux3.0.20/fs/proc。
shell上的位置:
文件:/proc/sched_debug
/proc/schedstat
目录:/proc/
p
i
d
/
t
a
s
k
/
pid/task/
pid/task/pid/
线程相关的字段: sched comm statm status schedstat stat
2.sched_debug字段
root@ubuntu:/proc# cat sched_debug
//调度的基准时间
Sched Debug Version: v0.11, 4.15.0-142-generic #146~16.04.1-Ubuntu
ktime : 13514998.586831
sched_clk : 13514405.524746
cpu_clk : 13514187.313553
jiffies : 4298271045
sched_clock_stable() : 1
sysctl_sched
.sysctl_sched_latency : 6.000000
.sysctl_sched_min_granularity : 0.750000
.sysctl_sched_wakeup_granularity : 1.000000
.sysctl_sched_child_runs_first : 0
.sysctl_sched_features : 2021179
.sysctl_sched_tunable_scaling : 1 (logaritmic)
//cpu的始终参数,本机为单核
cpu#0, 2294.780 MHz
.nr_running : 3
.load : 3145728
.nr_switches : 682047
.nr_load_updates : 540552
.nr_uninterruptible : 0
.next_balance : 4294.892296
.curr->pid : 4322
.clock : 13514186.330097
.clock_task : 13514186.330097
.cpu_load[0] : 3070
.cpu_load[1] : 3070
.cpu_load[2] : 3070
.cpu_load[3] : 3059
.cpu_load[4] : 2899
.avg_idle : 1000000
.max_idle_balance_cost : 500000
//cfs调度器的参数
cfs_rq[0]:/
.exec_clock : 0.000000
.MIN_vruntime : 144700.671361
.min_vruntime : 144703.661531
.max_vruntime : 144703.661531
.spread : 2.990170
.spread0 : 0.000000
.nr_spread_over : 0
.nr_running : 3
.load : 3145728
.runnable_weight : 3145728
.load_avg : 5075
.runnable_load_avg : 2005
.util_avg : 516
.removed.load_avg : 0
.removed.util_avg : 0
.removed.runnable_sum : 0
.tg_load_avg_contrib : 0
.tg_load_avg : 0
.throttled : 0
.throttle_count : 0
//rt调度器的参数
rt_rq[0]:
.rt_nr_running : 2
.rt_nr_migratory : 2
.rt_throttled : 1
.rt_time : 951.483224
.rt_runtime : 950.000000
//deadline的调度器的参数
dl_rq[0]:
.dl_nr_running : 0
.dl_nr_migratory : 0
.dl_bw->bw : 996147
.dl_bw->total_bw : 0
//线程的具体参数
runnable tasks:
S task PID tree-key switches prio wait-time sum-exec sum-sleep
-----------------------------------------------------------------------------------------------------------
S systemd 1 2108.859686 3201 120 0.000000 4752.932816 0.000000 0 0 /autogroup-2
S kthreadd 2 142322.322046 279 120 0.000000 13.208422 0.000000 0 0
3. schedstat字段
可以看见此字段如下:
root@ubuntu:/proc# cat schedstat
version 15
timestamp 4298472805
cpu0 0 0 0 0 0 0 1729419922293 4376331060505 800805
//kernel/sched_stats.h
static int __init proc_schedstat_init(void)
{
proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
return 0;
}
分别为版本号:SCHEDSTAT_VERSION,此参数内核写死;
时间戳信息,根据时钟中断进行更新;
/* runqueue-specific stats */
seq_printf(seq,
"cpu%d %u %u %u %u %u %u %llu %llu %lu",
cpu, rq->yld_count,
rq->sched_switch, rq->sched_count, rq->sched_goidle,
rq->ttwu_count, rq->ttwu_local,
rq->rq_cpu_time,
rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount);
seq_printf(seq, "\n");
第三部分对应为cpu上的rq结构体对应的部分参数;
4.proc/pid/task
此目录显示了进程下的所有线程组的信息,我们在此通过内核源码进行说明;
task目录是如何创建的;
/* for the /proc/TGID/task/ directories */
static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct task_struct *leader = NULL;
struct task_struct *task;
int retval = -ENOENT;
ino_t ino;
int tid;
struct pid_namespace *ns;
task = get_proc_task(inode);
if (!task)
goto out_no_task;
rcu_read_lock();
if (pid_alive(task)) {
leader = task->group_leader;
get_task_struct(leader);
}
rcu_read_unlock();
put_task_struct(task);
if (!leader)
goto out_no_task;
retval = 0;
switch ((unsigned long)filp->f_pos) {
case 0:
ino = inode->i_ino;
if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
goto out;
filp->f_pos++;
/* fall through */
case 1:
ino = parent_ino(dentry);
if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0)
goto out;
filp->f_pos++;
/* fall through */
}
/* f_version caches the tgid value that the last readdir call couldn't
* return. lseek aka telldir automagically resets f_version to 0.
*/
ns = filp->f_dentry->d_sb->s_fs_info;
tid = (int)filp->f_version;
filp->f_version = 0;
for (task = first_tid(leader, tid, filp->f_pos - 2, ns);
task;
task = next_tid(task), filp->f_pos++) {
tid = task_pid_nr_ns(task, ns);
if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
/* returning this tgid failed, save it as the first
* pid for the next readir call */
filp->f_version = (u64)tid;
put_task_struct(task);
break;
}
}
out:
put_task_struct(leader);
out_no_task:
return retval;
}