專門用語:
- 使用打字機(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_task的task_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節省堆疊空間2,thread_info佔約60Bytes的記憶體空間與task_struct佔約1.7KBytes比較起來小了不少。
1 最後被碰到的區域,以x86架構為例則是位址最小的區域。
2 堆疊空間僅有8K或4KBytes,取決於編譯Linux kernel時的設定。
[1] http://lxr.linux.no/ 或是參考之前文獻所自行產生的cross reference
No comments:
Post a Comment