5) activated
表示進程因什麼原因進入就緒態,這一原因會影響到調度優先順序的計算。activated 有四個值:
-1,進程從 TASK_UNINTERRUPTIBLE 狀態被喚醒;
0,預設值,進程原本就處於就緒態;
1,進程從 TASK_INTERRUPTIBLE 狀態被喚醒,且不在中斷上下文中;
2,進程從 TASK_INTERRUPTIBLE 狀態被喚醒,且在中斷上下文中。
activated 初值為 0,在兩個地方修改,一是在 schedule() 中,被恢複為 0,另一個就是 activate_task(),這個函數由 try_to_wake_up() 函數調用,用於啟用休眠進程:
如果是中斷服務程式調用的 activate_task(),也就是說進程由中斷啟用,則該進程最有可能是互動,因此,置 activated=2;否則置activated=1。
如果進程是從 TASK_UNINTERRUPTIBLE 狀態中被喚醒的,則 activated=-1(在try_to_wake_up()函數中)。
activated 變數的具體含義和使用見"最佳化了的優先順序計算方式"。
6) sleep_avg
進程的平均等待時間(以 nanosecond 為單位),在 0 到 NS_MAX_SLEEP_AVG 之間取值,初值為 0,相當於進程等待時間與已耗用時間的差值。sleep_avg 所代表的含義比較豐富,既可用於評價該進程的"互動程度",又可用於表示該進程需要啟動並執行緊迫性。這個值是動態優先順序計算的關鍵因子,sleep_avg 越大,計算出來的進程優先順序也越高(數值越小)。在下文"進程平均等待時間 sleep_avg" 中會詳細分析 sleep_avg 的變化過程。
7) interactive_credit
這個變數記錄了本進程的"互動程度",在 -CREDIT_LIMIT 到 CREDIT_LIMIT+1 之間取值。進程被建立出來時,初值為 0,而後根據不同的條件加 1 減 1,一旦超過 CREDIT_LIMIT(只可能等於 CREDIT_LIMIT+1),它就不會再降下來,表示進程已經通過了"互動式"測試,被認為是互動式進程了。interactive_credit具體的變化過程在"更精確的互動式進程優先"中會詳細描述。
8) nvcsw/nivcsw/cnvcsw/cnivcsw
進程切換計數。
9) time_slice
進程的時間片餘額,相當於 2.4 的 counter,但不再直接影響進程的動態優先順序。在"新的已耗用時間片表現"中專門分析了 time_slice 的行為。
10) first_time_slice
0 或 1,表示是否是第一次擁有時間片(剛建立的進程)。這一變數用來判斷進程結束時是否應當將自己的剩餘時間片返還給父進程(見"新的已耗用時間片表現")。
11) run_list
前面提到,優先順序數組 prio_array 結構中按順序排列了各個優先順序下的所有進程,但實際上數組中每一個元素都是 list_head 結構,以它為表頭的鏈表中的每一個元素也是 list_head,其中連結的就是 task_struct 中的 run_list 成員。這是一個節省空間的、加速訪問的小技巧:調度器在 prio_array 中找到相應的 run_list,然後通過 run_list 在 task_struct 中的固定位移量找到對應的 task_struct(參見 enqueue_task()、dequeue_task() 和 list.h 中的操作)。
12) array
記錄當前 CPU 的活躍就緒隊列(runqueue::active)。
13) thread_info
當前進程的一些運行環境資訊,其中有兩個結構成員與調度關係緊密:
preempt_count:初值為 0 的非負計數器,大於 0 表示核心不宜被搶佔;
flags:其中有一個 TIF_NEED_RESCHED 位,相當於 2.4 中的 need_resched 屬性,如果當前運行中的進程此位為 1,則表示應該儘快啟動調度器。
在 2.4 中,每個進程的 task_struct 都位於該進程核心棧的頂端(低址部分),核心可以通過棧寄存器 ESP 輕鬆訪問到當前進程的 task_struct。在 2.6 中,仍然需要頻繁訪問這個名為 current 的資料結構,但現在,進程核心棧頂儲存的是其中的 thread_info 屬性,而不是完整的 task_struct 了。這樣做的好處是僅將最關鍵的、訪問最頻繁的運行環境儲存在核心棧裡(仍然是兩個頁大小),而將 task_struct 大部分內容通過 thread_info::task 指標儲存在棧外,以方便擴充。thread_info 的分配方式和訪問方式與 2.4 中的 task_struct 完全相同,現在的 current 需要這樣來訪問:
/* 節選自[include/asm-i386/current.h] */
static inline struct task_struct * get_current(void)
{
return current_thread_info()->task;
}
#define current get_current()
其中current_thread_info()定義為:
/* 節選自[include/asm-i386/thread_info.h] */
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~8191UL));
return ti;
}