作者: sunmoon 這幾天身體不太好,進展不快.有時候突然發現在拼命的讀代碼的間隙裡,停一會想一想,收獲會更 大.特別是對於這種非常龐大的系統來說.把握整體的意義尤其重要.隨著對Linux整體的拆解,我對 於整個系統,已經不想開始是那麼模糊.好像已經度過了那個極點.不過我也應做好准備,因為一但 我對整個細節解讀時,肯定也會有同樣的經歷. 整個linux內核之所以這樣艱澀,難懂就在於它的整體性.想我們這樣很少寫萬行以上程序的人來 說,它就好像一個龐大的肉球.讓你不知道如何下嘴.不過一但咬破.就非常香美了.畢竟,讀這麼優 秀的代碼也是一種享受. 我個人認為linux 的內核難在這幾點:1,系統龐大,太多的變量,結構, 以及typedef定義的東西不 容易找到.2,作為操作系統,它的函數調用時動態的,讀不懂大量的makefile 你根本就不知道這50 M的東西是怎麼組織起來的,況且,你絕對不可以像跟蹤程序一樣用debug走一下.3, 龐大的數據結 構,可能是比較簡單的運算變得不容易讀. 因此在讀核的初級階段.我們應該善於想象,善於將不容易理解的部分用偽碼的理解方式走過,當我 們對大局把握好了,將整個結構拆解清楚了,在讀不遲.況且,雖內核本身來說,它所涉及到的運算, 結構. 本質上和課本上的沒有差別.(可惜我不是計算機系畢業的).只不過是內容多了一些罷了. 比如說進程調度這一部分,說白了,就是在調用fork()的時候,就產生一task_strut 類型的指針,它 包含進程調度所用到的一切信息.然後將這個指針插到隊列中去就行了,然後cpu 一次總隊類中取 出指針,分配給他們時間片. 而這個指針如何插入呢?說白了就是看它的weight,weight 的計算方法,有根據進程類型的不同由 不同的算法(實時進程,內核進程,普通進程).好了,這樣我們想一下<<數據結構中>>關於隊列的操 作,插入,刪除,插到隊頭,置於隊尾.再想一下,這些操作如何同操作系統的應用結合在一塊.例如; 好隊進程正在運行,突然,由於一硬件中斷.產生一進程,它必須馬上處理.系統應把它插入到隊頭. 好了.你可以讀一下/usr./src/linux/kenrel/sched.c,不要過那麼多全局變量,現在數據結構上走 過去,如下面的代碼: static inline void move_last_runqueue(strUCt task_struct * p) { struct task_struct *next = p->next_run; struct task_struct *prev = p->prev_run; /* remove from list */ next->prev_run = prev; prev->next_run = next; /* add back to list */ p->next_run = &init_task; prev = init_task.prev_run; init_task.prev_run = p; p->prev_run = prev; prev->next_run = p; } static inline void move_first_runqueue(struct task_struct * p) { struct task_struct *next = p->next_run; struct task_struct *prev = p->prev_run; /* remove from list */ next->prev_run = prev; prev->next_run = next; /* add back to list */ p->prev_run = &init_task; next = init_task.next_run; init_task.next_run = p; p->next_run = next; next->prev_run = p; } 如果你還不懂,你可能要先,在c語言和數據結構上下一點功夫.其他的模塊,我想也是大同小異, 不 過,也修補會這麼簡單.如內存管理中用到了好多平衡二叉樹的排序,遍歷等等.但總的結構時不變 的.只要可以通欄全局,在不開定義的情況下,可以讀懂全局變量的意思(其實,猜個八九不成問題), 看懂是不成問題的.起碼我是信心十足. 我應該在熟悉一下,計算機專業的軟件基礎課!!