我是如何学习写一个操作系统(九):文件系统
前言
這個(gè)應(yīng)該是這個(gè)系列的尾聲了,一個(gè)完整的操作系統(tǒng)可能最主要的也就是分成這幾大模塊:進(jìn)程管理、內(nèi)存管理和文件系統(tǒng)。計(jì)算機(jī)以進(jìn)程為基本單位進(jìn)行資源的調(diào)度和分配;而與用戶的交互,基本單位則是文件
生磁盤(pán)
文件正是對(duì)生磁盤(pán)的抽象
磁盤(pán)的組成
一個(gè)磁盤(pán)由多個(gè)盤(pán)面串聯(lián)而成,而一個(gè)盤(pán)面又被分為磁道,磁道又由扇區(qū)組成。
磁盤(pán)的訪問(wèn)單元就是扇區(qū),一個(gè)扇區(qū)為512字節(jié)
磁盤(pán)的使用
- CPU向磁盤(pán)的控制器發(fā)出一個(gè)指令
- 控制器開(kāi)始進(jìn)行尋道、旋轉(zhuǎn)和傳輸
- 最后完成后向CPU發(fā)送一個(gè)中斷
也就是向控制器發(fā)送柱面磁頭扇區(qū)等信息,然后等待回應(yīng)
盤(pán)塊
盤(pán)塊是對(duì)扇區(qū)的抽象
程序負(fù)責(zé)提高盤(pán)塊block,而磁盤(pán)驅(qū)動(dòng)負(fù)責(zé)從block計(jì)算出cyl,head,sec(CHS),最后傳遞到磁盤(pán)控制器上
磁盤(pán)訪問(wèn)時(shí)間 = 寫(xiě)入控制器時(shí)間 + 尋道時(shí)間 + 旋轉(zhuǎn)時(shí)間 + 傳輸時(shí)間
其中主要的時(shí)間都在尋道時(shí)間和旋轉(zhuǎn)時(shí)間,所以對(duì)扇區(qū)抽象成盤(pán)塊就可以一次訪問(wèn)多個(gè)扇區(qū)來(lái)節(jié)省磁盤(pán)的訪問(wèn)時(shí)間
磁盤(pán)調(diào)度
既然有多進(jìn)程交替執(zhí)行,就有可能多個(gè)進(jìn)程同時(shí)訪問(wèn)相同磁盤(pán)的情況,就需要一個(gè)請(qǐng)求隊(duì)列來(lái)處理所有請(qǐng)求,就會(huì)涉及到調(diào)度算法了
FCFS調(diào)度
FCFS是最公平最直觀的算法,也就是按照隊(duì)列順序來(lái)訪問(wèn)磁盤(pán),但是效率也很低下,磁頭會(huì)在不規(guī)律的磁道長(zhǎng)途奔襲
SSTF調(diào)度
SSTF算法就類似短作業(yè)優(yōu)先算法,先尋找更近距離的磁道,但是SSTF算法可能會(huì)產(chǎn)生饑餓問(wèn)題,過(guò)長(zhǎng)距離的磁道可能一直得不到處理
SCAN調(diào)度
SCAN算法就是SSTF算法的改良版,也就是進(jìn)行SSTF,但是在中途不會(huì)折返去尋找更短距離的磁道,這樣就避免了饑餓問(wèn)題
C-SCAN調(diào)度(電梯算法)
把掃描限定在一個(gè)方向,當(dāng)訪問(wèn)到某個(gè)方向的最后一個(gè)磁道時(shí),磁道返回磁盤(pán)相反方向磁道的末端,并再次開(kāi)始掃描。
文件和文件系統(tǒng)
文件是對(duì)磁盤(pán)的第三層抽象,扇區(qū)和盤(pán)塊分別是前兩層抽象。之所以有文件這層抽象是為了方便用戶的使用,在用戶的眼里,磁盤(pán)上的信息都可以看作是字符流。所以文件的抽象九可以看作是字符流到盤(pán)塊集合的映射關(guān)系
文件的邏輯結(jié)構(gòu)
從文件到盤(pán)塊的映射來(lái)看,一般有這幾種組織方式
順序文件
記錄是定長(zhǎng)的且按關(guān)鍵字順序排列??梢皂樞虼鎯?chǔ)或以鏈表形勢(shì)存儲(chǔ),在訪問(wèn)時(shí)需要順序搜索文件。順序文件有以下兩種結(jié)構(gòu):
第一種是串結(jié)構(gòu),各記錄之間的順序與關(guān)鍵字無(wú)關(guān)。通常的辦法是由時(shí)間來(lái)決定,即按存入時(shí)間的先后排列,最先存入的記錄作為第一個(gè)記錄,其次存入的為第二個(gè)記錄,以此類推。
第二種是順序結(jié)構(gòu),指文件中所有記錄按關(guān)鍵字順序排列。
在對(duì)記錄進(jìn)行批量操作時(shí),即每次要讀或?qū)懸淮笈涗?#xff0c;對(duì)順序文件的效率是所有邏輯文件中最高的;此外,也只有順序文件才能存儲(chǔ)在磁帶上,并能有效的工作。但順序文件對(duì)查找、修改、增加或刪除單個(gè)記錄的操作比較困難。索引文件
對(duì)于可變長(zhǎng)記錄的文件只能順序查找,系統(tǒng)開(kāi)銷較大,為此可以建立一張索引表以加快檢索速度,索引表本身是順序文件。在記錄很多或是訪問(wèn)要求高的文件中,需要引入索引以提供有效的訪問(wèn),實(shí)際中,通過(guò)索引可以成百上千倍的提高訪問(wèn)速度。
索引順序表
索引順序表是順序和索引兩種組織形勢(shì)的結(jié)合。索引順序文件將順序文件中所有記錄分為若干個(gè)組,為順序文件建立一張索引表,在索引表中為每組中的第一個(gè)記錄建立一個(gè)索引項(xiàng),其中含有該記錄的關(guān)鍵字值和指向該記錄的指針。
在實(shí)際的操作系統(tǒng)實(shí)現(xiàn)中,一般是采用多級(jí)索引
目錄和文件系統(tǒng)
文件系統(tǒng)或者說(shuō)目錄是對(duì)磁盤(pán)的第四個(gè)抽象,也就是抽象了整個(gè)磁盤(pán)
操作系統(tǒng)為了實(shí)現(xiàn)文件目錄,引入了稱為文件控制塊的數(shù)據(jù)結(jié)構(gòu)。
文件控制塊。
文件控制塊(FCB)是用來(lái)存放控制文件需要的各種信息的數(shù)據(jù)結(jié)構(gòu),以實(shí)現(xiàn)“按名存取”。FCB的有序集合稱為文件目錄,一個(gè)FCB就是一個(gè)文件目錄項(xiàng)。為了創(chuàng)建一個(gè)新文件,系統(tǒng)將分配一個(gè)FCB并存放在文件目錄中,稱為目錄項(xiàng)。
FCB主要包含以下信息:
文件目錄樹(shù)
在多級(jí)目錄下一般對(duì)磁盤(pán)就可以抽象為
FCB數(shù)組
FCB數(shù)組就是將所有盤(pán)塊的FCB信息都集中到一個(gè)數(shù)組中
數(shù)據(jù)盤(pán)塊集合
在每個(gè)數(shù)據(jù)盤(pán)塊里都包含一些目錄項(xiàng)用來(lái)找到子目錄,目錄項(xiàng)也就是文件名+對(duì)應(yīng)的FCB的“地址”,也就是去之前的FCB數(shù)組中找到相應(yīng)的FCB
在磁盤(pán)進(jìn)行格式化的時(shí)候,會(huì)存放一些信息用來(lái)知道一些磁盤(pán)信息和找到根目錄
inode位圖: 哪些inode空閑,哪些被占用
超級(jí)塊:記錄兩個(gè)位圖有多大等信息
盤(pán)塊位圖: 哪些盤(pán)塊是空閑的,硬盤(pán)大小不同這個(gè)位圖的大小也不同
文件的實(shí)現(xiàn)
在我之前實(shí)現(xiàn)的FragileOS里文件系統(tǒng)非常簡(jiǎn)陋,基本沒(méi)有什么好說(shuō)的。這其實(shí)也是為什么之前把這個(gè)系列改了一個(gè)方向來(lái)結(jié)合的看Linux0.11的代碼。所以來(lái)看一下Linux0.11里是怎么使用和實(shí)現(xiàn)文件系統(tǒng)的,
讀取文件
- 這是讀取文件的系統(tǒng)調(diào)用
- 函數(shù)首先對(duì)參數(shù)有效性進(jìn)行判斷
- 之后對(duì)文件的類型進(jìn)行判斷
- 如果是目錄文件或者是常規(guī)文件就執(zhí)行讀取操作
- 根據(jù)i節(jié)點(diǎn)和文件結(jié)構(gòu),讀取文件中數(shù)據(jù)。
- 首先判斷參數(shù)的有效性
- 之后循環(huán)的調(diào)用bread來(lái)讀取數(shù)據(jù)
- 之后復(fù)制chars字節(jié)到用戶緩沖區(qū)buf中
- 最后是修改該i節(jié)點(diǎn)的訪問(wèn)時(shí)間為當(dāng)前時(shí)間和返回讀取的字節(jié)數(shù)
文件寫(xiě)入
- 根據(jù)i節(jié)點(diǎn)和文件結(jié)構(gòu)信息,將用戶數(shù)據(jù)寫(xiě)入文件中
- 首先確定數(shù)據(jù)寫(xiě)入文件的位置
- 然后算出對(duì)應(yīng)的盤(pán)塊
- 然后用戶緩沖區(qū)buf中復(fù)制c個(gè)字節(jié)到告訴緩沖塊中p指向的開(kāi)始位置處
- 最后是修改該i節(jié)點(diǎn)的訪問(wèn)時(shí)間為當(dāng)前時(shí)間和返回讀取的字節(jié)數(shù)
文件目錄的實(shí)現(xiàn)
打開(kāi)創(chuàng)建文件
- 首先對(duì)參數(shù)進(jìn)行處理,然后搜索進(jìn)程結(jié)構(gòu)中文件結(jié)構(gòu)指針數(shù)組一個(gè)空閑的文件句柄
- 接著為打開(kāi)文件在文件表中尋找一個(gè)空閑結(jié)構(gòu)項(xiàng)
- 然后調(diào)用函數(shù)open_namei()執(zhí)行打開(kāi)操作,若返回值小于0,則說(shuō)明出錯(cuò),就釋放剛申請(qǐng)到的文件結(jié)構(gòu)
- 然后為不同的文件類型做一些特殊的處理
- 最后初始化打開(kāi)文件的文件結(jié)構(gòu),然后返回文件句柄
解析目錄
- 先根據(jù)當(dāng)前路徑的第一個(gè)字符來(lái)判斷當(dāng)前路徑是絕對(duì)路徑還是相對(duì)路徑
- 然后進(jìn)循環(huán)處理過(guò)程,分割每個(gè)目錄名
- 得到這個(gè)目錄名后,調(diào)用查找目錄項(xiàng)函數(shù)find_entry()在當(dāng)前處理的目錄中尋找指定名稱的目錄
- 如果找到這個(gè)目錄,就設(shè)置一些信息,然后繼續(xù)以該目錄項(xiàng)為當(dāng)前目錄繼續(xù)循環(huán)處理路徑名中的下一目錄名部分(或文件名)
轉(zhuǎn)載于:https://www.cnblogs.com/secoding/p/11442659.html
總結(jié)
以上是生活随笔為你收集整理的我是如何学习写一个操作系统(九):文件系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Pycharm如何在控制台输出窗口中使用
- 下一篇: 我是如何学习写一个操作系统(完结):总结