課程學習總結報告
這門課程剛開始的時候,孟老師將Linux核心與其他各個模組的關係用非常簡潔而又形象的圖畫表示出來,我認為,這張圖對任何一個Linux小白,都有非常好的引導意義,是Linux核心模型大的框架,如下圖所示。
經過大半個學期的學期,我也對Linux核心有了更多的認識。在我看來,作為作業系統最關鍵的一部分,Linux核心是連線計算機軟硬體的橋樑,起到了非常關鍵的承上啟下作用。向上延伸,它提供了各式各樣基礎且關鍵的API介面,供上層庫函式和程式通過系統呼叫來使用;向下延伸,它直接對接硬體設施。也就是說,Linux核心是一個“中介”,向“客戶”(應用程式)提供服務,並將“客戶”需求轉化為“施工方”(硬體)能夠理解的概念,以便專案落地。
對Linux核心模型再進一步瞭解,可以按照功能模組,再細分成程序管理、記憶體管理、虛擬檔案系統、網路系統和程序間通訊,如下圖所示。
1、程序管理:管理最核心的CPU資源,保證各個程序能夠合理地利用CPU資源完成自身任務。
2、記憶體管理:管理記憶體資源,使得記憶體被程序安全使用。
3、虛擬檔案系統:為方便對外設進行管理,將如硬碟、光碟等外設均抽象為虛擬檔案,Linux核心提供諸如open、write、read等介面函式對其統一管理。
4、網路系統:管理涉及網路操作的資源。
5、程序間通訊:為程序間交流資源提供渠道。
其中,程序管理為Linux核心最重要的部分,因為在作業系統中,程序是程式執行的動態實體,所有程序的工作開展都要依託於Linux核心的程序排程,其相互關係如下圖所示。
最終程式以程序的形式得到CPU資源而執行,當其需要調動下層資源時,會向Linux作業系統核心發出系統呼叫請求,執行環境從使用者態轉向核心態,在某個時間節點,完成預期功能,再返回使用者態繼續執行。
以上即為基於本人的有限認識對Linux系統概念模型的總結,接下來以“讀取檔案”的一系列流程為例,進一步完善對模型的認識
作業系統讀檔案hello.txt,大體可以劃分為如下流程:
1、為讀入檔案做準備
在例項程式執行到read函式時,軟中斷int 0x80通過中斷描述符表,跳到system_call,最後跳轉至system_read去執行.
int sys_read(unsigned int fd, char * buf, int count) { …… if (fd >= NR_OPEN || count < 0 || !(file = curren t-> file[fd])) ……return file_read(inode, file, buf, count); }
先檢查輸入引數的合理性,最後呼叫file_read函式讀取檔案。
2、確定要檔案內容的位置
int file_read(struct m_inode * inode, struct file * flip, char * buf, int count) { …… while(left) { if (nr = bmap(inode, (flip->f_pos)/BLOCK_SIZE)) …… } …… }
在while迴圈中,根據資料的實際組織方式,確定檔案內容在硬碟上的“塊號”。
3、將指定資料從硬碟讀至系統緩衝區
以硬體的“塊號”和“裝置號”為依據,從硬碟中將hello.txt對應的資料塊讀入緩衝區。
int file_read(struct m_inode * inode, struct file * flip, char * buf, int count) { ……
if(!(bh=bread(inode->i_dev, nr))) …… }
inode->i_dev為硬碟裝置號,nr為具體塊號,bread函式為讀盤指令。一旦開始從硬碟讀取資料,程序便轉為不可中斷的狀態,直到資料全部讀入緩衝區。
從中可以看出,上層程式讀取檔案時無需知曉任何具體硬體知識,由Linux核心完成涉及到底層的資料操作。
4、將資料拷貝至程式執行的指定空間
先檢測是否讀完指定的資料量
int file_read(struct m_inode * inode, struct file * flip, char * buf, int count) { ……
while(left) {
……
nr = filp->f_pos % BLOCK_SIZE;
chars = MIN(BLOCK_SIZE - nr, left);
……
} …… }
若沒有讀完,更新left的值,確定具體還有多少沒有讀完
int file_read(struct m_inode * inode, struct file * flip, char * buf, int count) { ……
while(left) {
……
filp->f_pos += chars;
left -= chars;
……
} …… }
最後把已經讀出來的資料拷貝到使用者空間
int file_read(struct m_inode * inode, struct file * flip, char * buf, int count) { ……
while(left) {
……
if (bh) {
char *p =nr + bh->b_data;
while(chars-->0)
put_fs_byte(*(p++), buf++);
brelse(bh);
}
……
} …… }
int file_read(struct m_inode * inode, struct file * flip, char * buf, int count) { ……
while(left) {
……
filp->f_pos += chars;
left -= chars;
……
} …… }
通過file_read函式中的while(left){……}迴圈,完成hello.txt檔案從硬碟到使用者執行空間的讀取。
課程總結:
在選這門課之前,我對Linux的認知僅限於一些諸如cd、ls等簡單的指令,對作業系統的認知也僅限於作業系統相關教材中抽象的文字描述,其他的東西一竅不通。通過這個學期的學習,通過老師們對實際的程式碼的講解,加深了我對作業系統的理解,大致知曉Linux是如何工作的,並且經過幾次實際的實驗操作,稍微有了跟蹤、除錯Linux系統的執行機制。
Linux作為一個廣受歡迎並普遍應用於各行各業的作業系統,無疑是非常成功的。其核心模組也是相當複雜,不甚晦澀。雖有老師們的悉心講解,但我感覺自己僅僅是摸到其新手門檻,要學習的知識浩如煙海,我瞭解到的僅是皮毛而已。
不過收穫還有非常之多的,特別是通過幾次實驗的實際操作,我學會了如何除錯核心,如何去逐步分析系統呼叫、如何去理解核心中的彙編程式碼等等。
感謝這門課程的學習,為我展示了計算機新世界的冰山一角!