作者簡介:
王建峰,對于技術方向(主要是嵌入式領域的OS方向的系統應用)感興趣,最近在學習作業系統基礎。同時也是某芯原廠的驅動工程師,主要是gpu領域的驅動軟體。https://gitee.com/hinzer/blog
- 1 概念介紹
- 1.1 什麼是作業系統?
- 1.2 如何了解中斷機制?
- 1.3 如何了解系統定時?
- 1.4 如何了解程序控制?
- 1.5 如何了解記憶體管理?
- 1.6 如何了解堆棧概念?
- 1.7 核心在源碼中的展現?
- 1.8 如何了解系統調用?
- 1.9 如何了解特權級?
- 2 流程分析
- 2.1 引導核心階段
- 2.2 核心啟動階段
- 2.3 init 程序啟動
- 2.4 shell 指令執行
Linux0.11 考古筆記
最近讀完《Linux 核心完全注釋》和《品讀 Linux0.11 核心代碼》,大緻了解下 Linux0.11 核心的全貌。在我了解這些屬于計算機基礎類的知識,是以在未來的工作場景不太可能會直接用到它們,如果用不到的話這些知識可能會随着時間的推進慢慢從我的記憶中消失,出于功利的角度我當然不希望學的東西過後就把它給忘記了,那豈不是白學了。
是以我希望能留下一些東西,趁着現在還有一點印象,我将找時間将這些知識重新梳理一遍,做成一份不完善的文檔。做這件事情對我的好處:梳理的過程中可以加深對作業系統的了解;文檔作為記憶的鑰匙幫助我回憶這些知識(可能在未來的某個場景能用得上)。
學習像核心這樣複雜的系統,我推測會經曆幾個重要的階段:了解專業術語,掌握程式流程;了解設計理念,掌握程式思想;了解源碼細節,掌握程式實作。目前大概在了解概念和了解設計思想這樣的階段,當然結合源碼能促進我對設計者的了解,但應該還沒有到達能實作的那個水準。現在最想做的事情是将核心諸多概念串成一個基本的圖景,是以文檔的側重點在如何解決這個需求。
1 概念介紹
1.1 什麼是作業系統?
這是一個容易引起歧義的概念,有一個比較狹隘的觀點認為核心是作業系統,比如 Linux 核心;另一個比較泛在的觀點是認為支援使用者程式的基礎軟體,都可以了解為作業系統的一部分。
1.2 如何了解中斷機制?
中斷是一個過程:程式在執行中,被意外打斷後轉去處理這種突發狀況,然後繼續原先的執行。在介紹下中斷的實作機制:從硬體的視角,在 80x86 組成的 PC 機中,采用了可程式設計中斷控制晶片 8259A 進行中斷源(産生中斷信号的裝置)管理,具體來說它支援程式設計(可進行初始化)和操作(可響應外部裝置的中斷請求)兩種狀态;從軟體的視角,在 Linux0.11 構成的系統中,對中斷信号的識别由一個 0 - 255 的數值(中斷号)來完成,由一個叫做中斷向量表的資料結構把中斷向量(中斷号)和中斷處理程式做一個定向關聯。
1.3 如何了解系統定時?
系統也由一個最小的時間機關,這個時間節拍就是系統運作的脈搏。從硬體的視角,PC 機使用可程式設計定時晶片 Intel 8253 時鐘源;從軟體的角度,在 Linux0.11 中設定這個定時晶片每隔 10ms 發出一個時鐘中斷信号,通過時鐘中斷處理程式,來累積系統滴答數、統計時間、輪轉時間片等等。
1.4 如何了解程序控制?
程式是一個可執行的檔案,而程序是一個執行中的程式執行個體。關于 Linux0.11 作業系統的程序設計,這裡僅側重了解幾個比較重要的概念。
- 分時技術:使得作業系統上同時運作多個程序,本質上是核心基于時間片進行程序排程;
- 使用者程序空間布局:包括代碼區、資料區、堆棧區;
- 程序隔離:系統隔離性包括程序與程序的隔離,使得程序隻能執行程序自己的代碼區和資料區和堆棧區;
- 使用者态和核心态:程序的運作時又分使用者态和核心态,一般來說指使用者态程序,如果程序執行執行系統調用接口會将程序狀态短時間陷入核心态;
- 程序通信:程序之間的通信也需要通過系統調用,就是在核心态中做;
1.5 如何了解記憶體管理?
為了高效的使用實體記憶體,Linux 核心有一套管理記憶體的方法。從硬體的視角,将實體記憶體按功能劃分為不同的記憶體域,其中包括核心子產品、高速緩沖區、虛拟盤、主記憶體區。從軟體的視角,核心通過分段将程序邏輯位址變成CPU線性位址,再通過分頁機制轉換成實體記憶體位址,這樣做的其中一個目的是讓程序認為自己擁有獨立的邏輯位址空間,達到空間的隔離性。
1.6 如何了解堆棧概念?
堆和棧是系統對記憶體的管理方式。從硬體的角度,堆棧段寄存器和堆棧指針寄存器中設定的值表示目前所使用的堆棧;從軟體的角度, Linux0.11 系統中的堆棧包括有:系統初始化的臨時堆棧、核心程式的使用堆棧、任務的核心态堆棧、任務的使用者态堆棧。
1.7 核心在源碼中的展現?
wangjianfeng@dev:~/source/Linux-0.11$ tree -d
.
├── boot
├── fs
├── include
│ ├── asm
│ ├── linux
│ └── sys
├── init
├── kernel
│ ├── blk_drv
│ ├── chr_drv
│ └── math
├── lib
├── mm
└── tools
└── bochs
└── bochsrc
1.8 如何了解系統調用?
系統調用是使用者程序打開核心大門的鑰匙,是核心層對外提供的一組通路核心的接口。
1.9 如何了解特權級?
特權模式支援作業系統的隔離性。從硬體的角度看,非特權級 ISA 允許使用者态的程序執行普通權限的指令(比如加法減法指令,跳轉指令)。特權級 ISA 允許核心态的程序執行特殊權限的指令(比如設定頁表指令,關時鐘中斷指令)。從軟體的角度,程序使用者态是非特權模式,隻有通過系統調用使程序暫時陷入核心态,讓使用者程式(非特權級)控制權轉移到核心(特權級)。
2 流程分析
根據《品讀 Linux0.11 核心代碼》這個專欄,它是按照系統啟動到運作的時間順序結合 Linux0.11 源碼來展開的,我根據專欄的内容進行二次整理。内容整體按照這個順序:引導核心階段、核心啟動階段、切換到使用者态、使用者程式運作、一個指令的執行。
2.1 引導核心階段
1)BIOS 程式
機器上電後 CPU 自動進入實模式,開始從 0XFFF0 位址處自動執行固化在 ROM 中的程式,這段程式會進行系統自檢并設定好中斷向量,還會從硬碟引導扇區讀程式到位址 0X7000 處并跳轉到這個位置繼續執行。
2)bootsect.s 程式
存放在硬碟引導扇區裡的 bootsect 程式,是由 bootsect.s 源檔案編譯成的。在執行 bootsect 時,它首先将自身拷貝新的位置,然後讀取磁盤其他扇區的内容。其中将 bootsect.s 搬到 0x9000 位址, setup.s 程式( 2~5 扇區)加載到 0x90200 位址,将 system 子產品( 240 個扇區)加載到 0x10000 位址。最後跳轉到 setup.s 程式繼續執行。
3)setup.s 程式
setup.s 程式執行時,首先會通過 int 0x10 觸發一個讀磁盤的中斷,通過 BIOS 的中斷處理讀取一些硬體參數到記憶體 0x9000 這個位置,然後将 system 子產品重定位到 0x0000 位址,然後切換實模式到保護模式,最後跳轉執行 system/head.s 程式。
4)head.s 程式
head.s 程式執行時,重新設定中斷描述符表和全局描述符表,然後設定幾個相關的段寄存器,然後啟動記憶體管理的分頁機制,最後跳轉到 main 函數。
2.2 核心啟動階段
1)擷取硬體參數并設定系統
2)系統初始化
3)新程序的誕生
2.3 init 程序啟動
2.4 shell 指令執行
0)一條指令
[[email protected]] cat info.txt | wc -l
3
1)敲擊鍵盤
2)輸出螢幕
3)shell 程序