1. 程式人生 > >linux排程器/proc資訊解讀

linux排程器/proc資訊解讀

轉載自 https://blog.csdn.net/wudongxu/article/details/8574755

 

注下面的時間或時刻都是從rq->clock中獲得的,而這個值是由update_rq_clock底層cpu來更新的。並且很多資訊是需要核心配置CONFIG_SCHEDSTATS才有。
/proc/<pid>/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/<pid>/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/<pid>/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/<pid>/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/<pid>/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