注:以下大部分內容摘自Linux內核編程入門篇和linux內核完全注釋
在工作的這段時間,發現我的visio畫圖熟悉了點點,總喜歡把什么源碼啊,結構啊之類的就當作流程圖來畫來理解,因為對於圖,有一個很直觀的認識,所以接下去也是以圖為中心。
關於linux內核體系結構
說到操作系統,我們都會知道windows操作系統,linux操作系統,蘋果的iOS操作系統,以前很火的塞班操作系統,還有最近消費類電子很火的Android操作系統。一個完整的操作系統分為4個部分。
可以把這個理解為我們用的手機。其中的硬件系統就是我們看到的整個手機了,cpu啊,內存啊,這些不拆開來看不到的,和觸摸屏啊,按鍵之類看以看到的。操作系統內核就是我們說的android了,不過他包括了linux的內核了。操作系統服務就是android的一套結構了,給我們直觀的就是那個有點炫的界面了。我們可以通過點擊來實現我們想要的功能。用戶應用就是我們常玩的QQ啊,導航啊,當然少不了各種好玩的游戲了,憤怒的小鳥,塗鴉跳,水果忍者,是不是又想玩一把?唉,還是好好學習吧,雖然手機就在旁邊。
對於linux內核的單內核模式的系統,有可以把他分為如下:
Linux內核又可分為5個大的模塊。
其關系和主要功能可以見下圖:
關於linux內存
物理內存可以分為下圖所示:
內核占用內存開始部分;接下來是共硬盤,軟盤使用的高速緩沖區部分,其中扣除顯存和bios的640k到1m;然后是虛擬盤;最后一部分是為所有程序可以使用的主內存區。
Linux內存管理中,段變換:將一個由段選擇符和段內偏移構成的邏輯地址轉換為一個線性地址。頁變換:將線性地址轉換為對應的物理地址。具體可見下圖所示:
虛擬地址:指的是由程序產生的由段選擇符和段內偏移地址兩個部分組成的地址。為什么叫它是虛擬的地址呢?因為這兩部分組成的地址並沒有直接訪問物理內存,而是要通過分段地址的變換機構處理或映射后才會對應到相應的物理內存地址。
段描述符:向CPU提供了將邏輯地址映射為線性地址所必要的信息。描述符是由程序編譯器、鏈接器、加載器或者操作系統創建的。
描述符表:保存描述符在描述符表中的,有兩類
1、 全局描述符表(Global descriptor table---GDT)
2、 局部描述符表(Local descriptor table---LDT)
描述符表是由8字節構成的描述符項的內存中的一個數組。處理器是通過使用GDT和LDTR寄存器來定位GDT表和當前的LDT表。最多可以含有8192(2^13)個描述符。
選擇符:邏輯地址的選擇部分,用於指定一描述符的,它是通過指定一描述符表並且索引其中的一個描述符項完成的。
段寄存器:處理器將描述符中的信息保存在段寄存器中,因而可以避免在每次訪問內存時查詢描述符表。
線性地址:通過指定一個頁表、頁表中的某一頁以及頁中的偏移值,從而間接地指向對應的物理地址。
頁表:一個簡單的32位頁指示器的數組。頁表本身也是一頁內存,因此它含有4K字節的內存,可容納1K個32位的項。
Offset = 2^12=4K, table =2^10, directory = 2^10,所以線性地址空間為2^10*2^10*4k=4G。
由於0.11內核把每個進程的最大可用的虛擬內存空間定義為64M,因此每個進程的邏輯地址可以用任務號*64M,就可以轉換到線性空間的地址。
關於linux進程
進程可以在內核態或者用戶態運行,當資源可用就被喚醒,進入就緒態;當進程處於可中斷睡眠狀態,收到信號可被喚醒;當處於不可中斷睡眠狀態,只能被使用wakeup等的喚醒;當進程處於暫停狀態,可發送信號使其進入就緒態;當僵死狀態,當已經停止運行,父進程還沒有調用wait查詢狀態,一旦父進程調用完wait取得子進程信息后,這個進程任務數據結構就會被釋放掉。
關於linux文件系統和源碼目錄
關於linux內核makefile
Linux makefile文件是編譯輔助工具軟件make的參數配置文件。Make工具軟件的主要用途是通過識別哪些文件已經被修改過,從而自動地決定在一個含有多個源程序文件的程序系統中哪些文件需要被重新編譯。
這里的makefile主要作用是指示make程序最終使用獨立編譯連接成的tools/目錄中的build執行程序將所有內核編譯代碼連接和合並成一個可運行的內核映像文件image。具體是對boot/目錄中的bootsect.s、setup.s使用8086匯編器進行編譯,分別生成各自的執行模塊。再對源代碼中的其他所有程序使用GNU的編譯器gcc/gas進行編譯,並連接成模塊system。再用build工具將這三塊組合成一個內核映像文件image。