Search Google

Wednesday, June 11, 2008

[Process Management] 如何找到current task的task_struct?

專門用語:

  • 使用打字機(Courier New)字體表示原始碼。
  • task/process即為Linux中的thread。
  • 文中的Linux與Linux kernel指的皆為作業系統核心。
  • 使用斜體字型標示Linux中的資料結構,變數或函式名稱。

Kernel版本:
  • v2.6.24.3

task_struct為關鍵字使用LXR[1]進行搜尋後會發現有許多類似下面這行程式碼:
struct task_struct *xxx = current;

因此我們再繼續搜尋current,便發現current其實是個macro:
#define current get_current()

get_current函式的回傳值為current_task亦即指到current task的task_struct的指標:
return x86_read_percpu(current_task);

因此藉由直接呼叫current便可取得current task的task_struct。
在兩種時機下current_task會被更新,開機時與Linux讓CPU執行另一個task之前。
開機的過程中current_task存放著作業系統中第一個thread init_tasktask_struct的位址:
DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;

在Linux讓CPU執行另一個task之前會間接呼叫到__switch_to函式,此函式把將被執行的task的task_struct位址存入current_task
x86_write_percpu(current_task, next_p);

在2.6.22以後的kernel中才以此方法取得current task的task_struct,與之前使用堆疊指標計算出task_struct的相對位址的方法相比節省了不少計算位址所需的時間。利用堆疊指標的方法為先呼叫先呼叫current_thread_info取得thread_info
return (struct thread_info *)(current_stack_pointer & ~(THREAD_SIZE - 1));

再透過thread_info裡的task取得task_struct

struct thread_info {
struct task_struct *task; /* main task structure */
....
}


在2.4以前的kernel中直接將task_struct存放於堆疊的最下方1並沒有使用thread_info轉介,2.6以後的kernel才引入thread_info節省堆疊空間2thread_info佔約60Bytes的記憶體空間與task_struct佔約1.7KBytes比較起來小了不少。



1 最後被碰到的區域,以x86架構為例則是位址最小的區域。
2 堆疊空間僅有8K或4KBytes,取決於編譯Linux kernel時的設定。


[1] http://lxr.linux.no/ 或是參考之前文獻所自行產生的cross reference

No comments: