linux调度器(十)——调度器/proc信息解读

转载自:
http://blog.csdn.net/wudongxu/article/details/8574755?reload

注下面的时间或时刻都是从rq->clock中获得的,而这个值是由update_rq_clock底层cpu来更新的。并且很多信息是需要内核配置CONFIG_SCHEDSTATS才有。
/proc//sched
$cat /proc/28733/sched

cpu_test (28733, #threads: 1)

se.exec_start : 2781299327.397282 //此进程最近被调度到的开始执行时刻(这个值是每次update_curr都进行更新)
se.vruntime : 3144603.079903 //虚拟运行时间
se.sum_exec_runtime: 2843625.998498 //累计运行的物理时间时间
se.wait_start : 0.000000 //最近一次当前进程被入队的时刻
se.sleep_start : 0.000000 //此进程最近一次被从队列里取出,并被置S状态的时刻
se.block_start : 0.000000 //此进程最近一次被从队列里取出,并被置D状态的时刻
se.sleep_max : 0.000000 //最长处于S状态时间
se.block_max : 0.000000 //最长处于D状态时间
se.exec_max : 1.004266 //最长单次执行时间
se.slice_max : 998.456300 //曾经获得时间片的最长时间
se.wait_max : 0.455235 //最长在就绪队列里的等待时间
se.wait_sum : 15.615407 //累计在就绪队列里的等待时间
se.wait_count : 3147 //累计等待次数
se.iowait_sum : 215.825267 //io等待时间
se.iowait_count : 67 //io等待次数 io_schedule调用次数
sched_info.bkl_count: 0 //此进程大内核锁调用次数
se.nr_migrations : 0 //需要迁移当前进程到其他cpu时累加此字段
se.nr_migrations_cold: 0
se.nr_failed_migrations_affine: 194 //进程设置了cpu亲和,进程迁移时检查失败的次数
se.nr_failed_migrations_running: 0
se.nr_failed_migrations_hot: 0 //当前进程因为是cache hot导致迁移失败的次数
se.nr_forced_migrations : 0 //在当前进程cache hot下,由于负载均衡尝试多次失败,强行进行迁移的次数
se.nr_wakeups : 0 //被唤醒的累计次数(从不可运行到可运行)
se.nr_wakeups_sync : 0 //同步唤醒次数,即a唤醒b,a立刻睡眠,b被唤醒的次数
se.nr_wakeups_migrate : 0 //被唤醒得到调度的当前cpu,不是之前睡眠的cpu的次数
se.nr_wakeups_local : 0 //被本地唤醒的次数(唤醒后在当前cpu上执行)
se.nr_wakeups_remote : 0 //非本地唤醒累计次数
se.nr_wakeups_affine : 0 //考虑了任务的cache亲和性的唤醒次数
se.nr_wakeups_affine_attempts: 0
se.nr_wakeups_passive : 0
se.nr_wakeups_idle : 0
avg_atom : 903.886204 //本进程平均耗时sum_exec_runtime/ nr_switches
avg_per_cpu : 0.000001
nr_switches : 3146 //主动切换和被动切换的累计次数
nr_voluntary_switches : 0 //主动切换次数(由于prev->state为不可运行状态引起的切换)
nr_involuntary_switches : 3146 //被动切换次数
se.load.weight : 1024 //该se的load
policy : 0 //调度策略 normal
prio : 120 //优先级(nice=0)
clock-delta : 51
大多数字段的计算在sched.c及sched_fair.c里,在这两个文件里搜索相应的字段就能得到相应的计算方法。

/proc//schedstat
$cat /proc/28733/schedstat
5726055470233 30451531 6336
First: time spent on the cpu, task->se.sum_exec_runtime,这个值与上面的se.sum_exec_runtime一样只是上面的除于1,000,000
Second:time spent waiting on a runqueue,这个值与上面的se.wait_sum一样
Third: of times run on this cpu, task->sched_info.pcount,这个值跟上面的se->nr_switches一样
该信息的入口在fs/proc/base.c的proc_pid_schedstat函数里。

/proc//status
$cat /proc/28733/status
Name: cpu_test
State: R (running)
Tgid: 28733
Pid: 28733
PPid: 5573
TracerPid: 0
Uid: 52170 52170 52170 52170 // uid euid suid fsuid
Gid: 100 100 100 100 // gid egid sgid fsgid
Utrace: 0
FDSize: 256
Groups: 100 19051 //启动该进程的用户所属的组的id,并不是组调度的组
VmPeak: 3976 kB
VmSize: 3912 kB //任务虚拟地址空间的大小 (total_vm-reserved_vm),其中total_vm为进程的地址空间的大小,reserved_vm:进程在预留或特殊的内存间的物理页,该值也是top的VIRT字段
VmLck: 0 kB //任务已经锁住的物理内存的大小。锁住的物理内存不能交换到硬盘 (locked_vm)
VmHWM: 328 kB //文件内存映射和匿名内存映射的大小
VmRSS: 328 kB //应用程序正在使用的物理内存的大小,就是用top的res字段
VmData: 44 kB //程序数据段的大小(所占虚拟内存的大小),存放初始化了的数据; (total_vm-shared_vm-stack_vm)
VmStk: 88 kB //任务在用户态的栈的大小 (stack_vm)
VmExe: 4 kB //程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库 (end_code-start_code)
VmLib: 1700 kB //被映像到任务的虚拟内存空间的库的大小 (exec_lib)
VmPTE: 32 kB //该进程的所有页表的大小,单位:kb
VmSwap: 0 kB
Threads: 1 //线程数
SigQ: 1/193060 //待处理信号的个数
SigPnd: 0000000000000000 //屏蔽位,存储了该线程的待处理信号
ShdPnd: 0000000000000000 //屏蔽位,存储了该线程组的待处理信号
SigBlk: 0000000000000000 //存放被阻塞的信号
SigIgn: 0000000000000000 //存放被忽略的信号
SigCgt: 0000000000000000 //存放被捕捉到的信号
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed: 000008 //可以使用的cpu bit
Cpus_allowed_list: 3 //可以使用的cpu id list
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 //可使用的mem
Mems_allowed_list: 0 //可使用的mem list
voluntary_ctxt_switches: 0 //主动的切换
nonvoluntary_ctxt_switches: 8310 //被动的切换
入口在fs/proc/array.c的proc_pid_status函数里,参考http://www.kerneltravel.net/?p=294

/proc//stat
在内核中,该文件的内容由do_task_stat函数(fs/proc/array.c)写。主要操作是
28733 (cpu_test) R 5573 28733 5573 34824 5573 4202496 176 0 0 0 1797172 80 0 20 0 1 0 2782750364005888 82 184467440737095516154194304 4195884 140733625322688 140733625322136 41954610 0 0 0 0 0 0 17 3 00 0 0 0
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”,
1 .pid_nr_ns(pid, ns), //pid
2 .tcomm, //进程名
3 .state, //进程状态
4 .ppid, //父进程号
5 .pgid, //线程组ID
6 .sid, //会话组ID
7 .tty_nr, //该进程的tty终端的设备号,INT(34817/256)=主设备号,(34817-主设备号)=次设备号
8 .tty_pgrp, //终端的进程组号,当前运行在该进程所在终端的前台进程(包括shell应用程序)的PID
9 .task->flags, //进程标志位,查看该进程的特性(定义在/include/kernel/sched.h中)
10.min_flt, //累计进程的次缺页数(Copy on Write页和匿名页)
11.cmin_flt, //该进程所有的子进程发生的次缺页的次数
12.maj_flt, //主缺页数(从映射文件或交换设备读入的页面数)
13.cmaj_flt, //该进程所有的子进程发生的主缺页的次数
14.cputime_to_clock_t(utime), //该进程在用户态运行的时间,单位为jiffies
15.cputime_to_clock_t(stime), //该进程在核心态运行的时间,单位为jiffies
16.cputime_to_clock_t(cutime), //该进程所有的子进程在用户态运行的时间总和,单位为jiffies
17.cputime_to_clock_t(cstime), //该进程所有的子进程在内核态运行的时间的总和,单位为jiffies
18.priority, //进程的优先级
19.nice, //进程的静态优先级
20.num_threads, //该进程所在的线程组里线程的个数
21.//0
22.start_time, //该进程创建的时间
23.vsize, //该进程的虚拟地址空间大小
24.mm ? get_mm_rss(mm) : 0, //该进程当前驻留物理地址空间的大小
25.rsslim, //该进程能驻留物理地址空间的最大值
26.mm ? (permitted ? mm->start_code : 1) : 0, //该进程在虚拟地址空间的代码段的起始地址
27.mm ? (permitted ? mm->end_code : 1) : 0, //该进程在虚拟地址空间的代码段的结束地址
28.(permitted && mm) ? mm->start_stack : 0, //该进程在虚拟地址空间的栈的结束地址
29.esp, //esp(32 位堆栈指针) 的当前值,与在进程的内核堆栈页得到的一致
30.eip, //指向将要执行的指令的指针, EIP(32位指令指针)的当前值
31.task->pending.signal.sig[0] & 0x7fffffffUL, //待处理信号的位图,记录发送给进程的普通信号
32.task->blocked.sig[0] & 0x7fffffffUL, //阻塞信号的位图
33.sigign .sig[0] & 0x7fffffffUL, //忽略的信号的位图
34.sigcatch .sig[0] & 0x7fffffffUL, //被捕捉的信号的位图
35.wchan, //如果该进程是睡眠状态,该值给出调度的调用点
36.0UL,
37.0UL,
38.task->exit_signal, //该进程结束时,向父进程所发送的信号
39.task_cpu(task), //运行在哪个CPU上
40.task->rt_priority, //实时进程的相对优先级别
41.task->policy, //进程的调度策略
42.(unsigned long long)delayacct_blkio_ticks(task),
43.cputime_to_clock_t(gtime),
44.cputime_to_clock_t(cgtime));
注:这个输出的中间自动填充了个0,在22 start_time前。参考http://www.kerneltravel.net/?p=291

/proc/sched_debug
这个打印出所有cpu的信息,这里我们过滤出cpu3来解释
$cat /proc/sched_debug | grep “cpu#3” -A 73
Sched Debug Version: v0.09, 2.6.32-220.23.1.tb704.el6.x86_64 #1
now at 2805981745.049080 msecs
.jiffies : 7100649040 //cpu时间
.sysctl_sched_latency : 20.000000
.sysctl_sched_min_granularity : 4.000000
.sysctl_sched_wakeup_granularity : 4.000000
.sysctl_sched_child_runs_first : 0.000000
.sysctl_sched_features : 3183
.sysctl_sched_tunable_scaling : 1 (logaritmic)
cpu#3, 2399.773 MHz
.nr_running : 2 //cpu3 rq运行队列的进程个数(包括正在运行的)
.load : 2048 //cpu3 rq运行队列的load
.nr_switches : 42606615 //cpu3累计的进程切换次数
.nr_load_updates : 220734972 //load更新次数,也是调用update_cpu_load次数
.nr_uninterruptible : 0 // uninterruptible发生的次数
.next_balance : 7100.059585 //下次执行负载均衡的时间
.curr->pid : 25329 //当前运行的进程pid
.clock : 2801062666.343504 //当前运行队列的clock
.cpu_load[0] : 2048 //该cpu的历史load
.cpu_load[1] : 2048
.cpu_load[2] : 2048
.cpu_load[3] : 2048
.cpu_load[4] : 2048
.yld_count : 1 //调用yield次数
.sched_switch : 0
.sched_count : 160158232 //调用schedule的次数
.sched_goidle : 21108490 //切换到idle进程的次数
.avg_idle : 1000000 // cpu处于idle的平均时间
.ttwu_count : 21244621 //此cpu try_to_wake_up唤醒进程的次数
.ttwu_local : 20424010 //本地唤醒的次数,即进程睡眠前所在cpu为当前cpu
.bkl_count : 1 //此cpu上大内核锁调用次数
//下面是相应的cfs_rq内容,另外我们的执行进程在/cgroup/one 这个二级cgroup里
cfs_rq[3]:/one //one group
.exec_clock : 22907786.300379 //
.MIN_vruntime : 22901158.741275 //红黑树最左边的vruntime
.min_vruntime : 22901158.741275 //cfs_rq当前的min_vruntime
.max_vruntime : 22901158.741275 //最右边的vruntime(这里因为只有一个,另一个在运行,所以最左与最右相等)
.spread : 0.000000
.spread0 : -300525615.387521 // cpu0上的min_vruntime与当前cpu的min_vruntime差值
.nr_spread_over : 0
.nr_running : 2 //该cfs_rq运行队列的进程个数(注:虽然运行的进程不在红黑树里,但是它还是cfs_rq里)
.load : 2048 //该cfs_rq的load,是它下面两个进程的load之和(在account_entity_enqueue、account_entity_dequeue更新)
.load_avg : 16496.090916 //update_cfs_load的统计值
.load_period : 8.054731
.load_contrib : 2047
.load_tg : 2047
.se->exec_start : 2801062666.343504 //该cgroup的se调度实体(非它下面进程的se,而是它自身的se)下面的关于se的内容与每个进程自身的/proc//sched内的含意是一样的
.se->vruntime : 188458882.115828
.se->sum_exec_runtime : 22907786.300379
.se->wait_start : 0.000000
.se->sleep_start : 0.000000
.se->block_start : 0.000000
.se->sleep_max : 0.000000
.se->block_max : 0.000000
.se->exec_max : 1.073055
.se->slice_max : 0.000000
.se->wait_max : 0.041254
.se->wait_sum : 121.099885
.se->wait_count : 28673
.se->load.weight : 2048 //这个se本身的load,它是通过update_cfs_shares更新

cfs_rq[3]:/ //同上
.exec_clock : 182645727.024410
.MIN_vruntime : 0.000001
.min_vruntime : 188458882.115828
.max_vruntime : 0.000001
.spread : 0.000000
.spread0 : -134967892.012968
.nr_spread_over : 4
.nr_running : 1
.load : 2048
.load_avg : 0.000000
.load_period : 0.000000
.load_contrib : 0
.load_tg : 0

runnable tasks: //运行队列里的进程,有两个28733,25329,并且当前运行的是25329

task PID tree-key switches prio exec-runtime sum-exec sum-sleep

    cpu_test 28733  22901158.741275     26280   120  22901158.741275  22600181.659870         0.000000 /one

R cpu_test 25329 22901163.146132 404 120 22901163.146132 6413.013913 0.000000 /one

tree-key:调度进程的se->vruntime;switches:主动与被动切换之和;exec-runtime:se->vruntime;sum-exec:se->sum_exec_runtime(实际运行的物理时间);sum-sleep:se.sum_sleep_runtime;最后加所属的cgroup
该信息的打印入口在sched_debug.c的sched_debug_show函数。
注:上面的很多信息是从网上搜索,再加上自己对调度器相关字段的验证,其它的内容没有验证
参考资料
http://chxxxyg.blog.163.com/blog/static/1502811932012912546208/
http://blog.csdn.net/chenyu105/article/details/7068758
proc目录解析:http://www.kerneltravel.net/?p=294
rq结构的注释:http://blog.csdn.net/bullbat/article/details/7160246

猜你喜欢

转载自blog.csdn.net/yuzaipiaofei/article/details/78140356