xv6作業系統實際上可理解為一個閹割到只剩下核心架構的UNIX作業系統。xv6使用了傳統的kernel概念,每個Process都需要藉由system call進入kernel來執行,而執行完後便會返回至user space。
Process主要由2個部分所組成:(1)user space的memory(指令、資料、stack)(2)只有kernel才能查看的Process執行狀態。
xv6具有分時特性,也就是說系統會決定目前kernel要執行哪個Process以及要執行多久,若在時間內該Process還沒執行完便會把他目前的狀態暫存起來並把執行權轉移給下一個待執行的Process;等到下一次輪到該Process獲得執行權時便會把原本暫存起來的狀態再load回來好讓kernel知道之前已經執行到哪了。
Pipe是一個在kernel中的buffer,他負責暫存File descriptor(都是以一個讀、一個寫為一組來暫存),每個Process都可藉由pipe來與另一個Process進行溝通。
換言之,如果一個Process需要用到的資料正好另一個Process有的話便可藉由pipe直接獲得,不需要大老遠去硬碟中找資料。
Process實際上是一個抽象概念,它會讓程式以為整個系統(包括硬體)在當下就只有執行他自己而已。
Process會提供一個虛擬的記憶體空間(這個虛擬空間足以容納整個程式),並且將虛擬空間中的每一個address與實際的資料儲存位置進行mapping。
開機時,系統會先進行初始化,然後將boot loader載入RAM並且開始執行;之後boot loader會把xv6的kernel載入進來並從entry部分開始執行;entry開始執行後便會開始建立page table,此時entry會將entrypgdir的實際位置載入至控制暫存器%cr3中;接著entry會跳到kernel本身的C code中開始執行main function;main function會先把一些硬體設備跟其他子系統初始化,之後便開始呼叫userinit以建立第一個Process;最後mpmain便會呼叫scheduler開始執行Process。
xv6的檔案系統使用了類似Unix檔案系統的檔案、目錄跟路徑名,並且把所有資料都存在硬碟之中。
xv6的檔案系統主要分成7層:
xv6檔案系統將硬碟分成許多的block。第0號負責儲存開機程式,而檔案系統無法動到此block;第1號負責儲存整個檔案系統的核心程式-又稱mfks(如架構、i-number數等等);第2號之後開始負責記錄logging,之後負責記錄inodes,再之後負責記錄每個inode與檔案資料的實際對應位置,這些都是需要紀錄多少就提供多少block;最後剩下的都是用來儲存檔案的實際資料。
在這一層中所有在硬碟裡的block一次只能有一個block暫存在buffer中,而且同時也只有一個kernel能使用,如果有別的kernel需要使用必須等到當前在使用的kernel使用完並發送release信號後才能進行使用權轉移,以此來確保硬碟中所有資料的一致性。
此外該kernel在使用資料時若需要的資料不在這個buffer裡的這一個block的話就必須先把該block寫回硬碟後在重新尋找需要的block,但反之若需要的資料都在同一個block的話便可直接在buffer中存取,以加快運作效率。(簡單來說跟RAM的運作原理幾乎一樣)
在這一層中系統會把一個system call中所有需要寫入資料的動作都紀錄成一個清單並存在logging block中,而系統在執行時則會根據該清單依序進行操作,只有在清單上的動作都執行完畢後才會把該清單刪除。因此即使在執行中發生crash,在系統重啟後只要照著原本那份清單重做一次就行了。
舉例來說,如果有一個清單有10個寫入動作,但是系統在執行第10個動作時因為斷電而系統重啟,此時大不了就是重新再執行一次前面的9個動作(因為第10個動作還沒執行完,所以該清單還不會被刪掉)。因此無論如何都只會有還沒執行的system call跟要重做一次的system call而已,不會有做到一半重啟系統後忘了之前做到哪裡的問題。
因為一個檔案的大小可能超過一個block的大小,所以一個檔案有可能會被分割成數個部分並個別儲存在不同的block中。因此在這一層中系統會將一個檔案的所有資料(如檔案大小、存放此檔案資料的block的address等等)全部彙整成一個inode並記錄在inodes block中,並且為該inode編號。
當系統收到訊息需要幾號inode(xxx檔案)的哪個資料時便會去查找該inode並且去看需要的資料是對應到哪個block中。(換言之就是類似該檔案的目錄,方便系統在該檔案中照出需要的資料在哪裡)
在這一層中系統會建立一個目錄架構,將在此目錄下的檔案或子目錄整合在一起,並且將檔案名稱與其實際是幾號inode所對應起來。(換言之就像是DNS,檔案名就像是一般人常用的xxx.com.tw之類的,而inode就像140.118.xxx.x之類的)
在這一層中系統會為每個檔案提供一個路徑名,而路徑名的取得則是利用遞迴的方式逐一查訪每個目錄去尋找那個要給他路徑名的檔案,當找到的時候便會回傳該位置的目錄名稱,最後在把這些目錄名稱連接在一起形成一個路徑。
舉例來說,在"c:\哲學\xxx.avi"中會先以遞迴方式去尋找xxx.avi,當找到該檔案時便會回傳"哲學"這個目錄,之後因為遞迴的關係又會回傳"c:(c槽)",最後再加上檔案自身的名稱便會形成路徑名。
因為在UNIX中所有的資料皆可用"檔案"的形式呈現(包括一般的檔案跟系統檔),而xv6檔案系統也承襲了此一概念,因此在這一層中系統會提供一個抽象化的介面來讓kernel對各種"檔案"進行各種操作。