😀前端入門操做系統知識,這一篇就夠啦!

此文針對非科班同窗來補充程序猿必備的基礎知識。前端

好了,開擼操做系統!linux

弱弱的問一問: 要操做系統幹嗎?

這裏先不講操做系統的概念了,由於文字太生硬了,咱們只須要看一個簡單的例子:算法

  • 在咱們的JS代碼裏,只須要輸入 console.log(1+1); 就能夠在瀏覽器面板中看到2,這其中發生了什麼事情呢?(簡單掃一眼)
  • 首先鍵盤輸入代碼1+1到顯示器輸出2, 須要CPU控制鍵盤(輸入設備) ,將獲取的1+1指令放入內存
  • 而後CPU的控制器從內存中取出指令,並分析出指令是讓計算機作一個1+1的加法運算
  • 此時CPU的控制將控制CPU的運算器作1+1的加法運算,並得出結果2
  • 最後CPU控制器控制運算器將結果返給內存,內存也在CPU控制器的控制下,將結果2返回給屏幕(輸出設備)

好了,這裏問題是,若是沒有操做系統,一個簡單的1+1運算,你的js代碼還須要考慮這些硬件的協調工做,好比你的代碼要協調CPU資源何時讀取你的代碼,何時把進程切換到別的進程。。。這些髒活累活都是操做系統幫你屏蔽了,要不這代碼可咋寫啊。。。sql

弱弱的問一問: 前端學這個幹嗎?

很早之前看樸零大神的《深刻淺出NodeJS》的時候,講到進程間通訊,有一句大概說,windows平臺進程間通訊用的是管道,linux平臺用的是domain socket,我一看就傻眼了,啥是進程間通訊?啥是管道?啥是domain socket?😭 看不懂啊.... 這些都是跟操做系統進程的知識相關)。數據庫

啥也了不說了,兄弟,學習的小車已經粗發了!編程

二、操做系統運行機制和體系結構

預備知識: 什麼是指令(更詳細內容請看個人計算機組成原理文章)windows

好比說,以下圖(簡單掃一下便可):瀏覽器

a+b是一段程序代碼,a+b在CPU看來並不能一步完成,能夠翻譯成以下:

// 意思是將內存的16號單元數據,放到A寄存器,
LOAD A, 16
// 意思是將內存的16號單元數據,放到B寄存器
LOAD B, 17
// 存器裏的A,B數據相加,獲得C
ADD C, A, B
複製代碼

這裏就能夠看得出來,指令是CPU識別執行的最基本命令。

2.1 兩種指令、兩種處理器狀態、兩種程序

假如說一個用戶能夠隨意把服務器上的全部文件刪光,這是很危險的。因此有些指令普通用戶是不能使用的,只能是權限較高的用戶能使用。此時指令就分爲了兩種,以下圖:

這就引出一個問題:CPU如何判斷當前是否能夠執行特權指令? 以下圖: CPU一般有兩種工做模式即:內核態用戶態,而在PSW(這個不用管,就知道有一個寄存器的標誌位0表示用戶態,1表示核心態)中有一個二進制位控制這兩種模式。

對於應用程序而言,有的程序能執行特權指令,有的程序只能執行非特權指令。因此操做系統裏的程序又分爲兩種:

2.2 操做系統內核簡單介紹

從下圖,咱們先看看操做系統內核包含哪些

操做系統內核中跟硬件緊密相關的部分有:

  • 時鐘管理。操做系統的時鐘管理是依靠硬件定時器的(具體硬件怎麼實現我也不太清楚,好像是靠硬件週期性的產生一個脈衝信號實現的)。時鐘管理至關重要,好比咱們獲取時間信息進程切換等等都是要依靠時鐘管理。
  • 中斷處理(下一小節會詳細介紹)。
  • 原語(後面會有案例提到)。如今能夠簡單理解爲用來實現某個特定功能,在執行過程當中不可被中斷的指令集合。原語有一個很是重要的特性,就是原子性(其運行一鼓作氣,不可中斷)。

2.3 中斷

  • 在程序運行過程當中,系統出現了一個必須由CPU當即處理的狀況,此時,CPU暫時停止程序的執行轉而處理這個新的狀況的過程就叫作中斷

下面舉一個例子:

第一個應用程序在用戶態執行了一段時間後 接着操做系統切換到核心態,處理中斷信號

  • 操做系統發現中斷的信號是第一個程序的時間片(每一個程序不能一直執行,CPU會給每一個程序必定的執行時間,這段時間就是時間片)用完了,應該換第二個應用程序執行了
  • 切換到第2個進程後,操做系統會將CPU使用權交換給第二個應用程序,接着第二個應用程序就在用戶態下開始執行。
  • 進程2須要調用打印機資源,這時會執行一個系統調用(後面會講系統調用,這裏簡單理解爲須要操做系統進入核心態處理的函數),讓操做系統進入核心態,去調用打印機資源
  • 打印機開始工做,此時進程2由於要等待打印機啓動,操做系統就不等待了(等到打印機準備好了,再回來執行程序2),直接切換到第三個應用程序執行
  • 等到打印機準備好了,此時打印機經過I/O控制器會給操做系統發出一箇中斷信號,操做系統又進入到核心態,發現這個中斷是由於程序2等待打印機資源,如今打印機準備好了,就切換到程序2,切換到用戶態,把CPU給程序2繼續執行。

好了,如今能夠給出一個結論,就是用戶態、核心態之間的切換是怎麼實現的?

  • "用戶態 ---> 核心態"是經過中斷實現的。而且中斷時惟一途徑
  • "核心態 ---> 用戶態"的切換時經過執行一個特權指令,將程序狀態的標誌位設爲用戶態。

2.4 中斷的分類

舉一個例子,什麼是內中斷和外中斷:

接着說以前的範桶同窗,小時候不愛學習,每次學習着學習着忽然異想天開,回過神來已通過好好長一段時間,這是內部中斷。想着想着老師走過來,給了範捅一嘴巴,這是外部中斷

官方解釋以下:

  • 內中斷常見的狀況如程序非法操做(好比你要拿的的數據的內存地址不是內存地址,是系統沒法識別的地址),地址越界(好比系統給你的程序分配了一些內存,可是你訪問的時候超出了你應該訪問的內存範圍)、浮點溢出(好比系統只能表示1.1到5.1的範圍,你輸入一個100, 超出了計算機能處理的範圍),或者異常陷入trap(是指應用程序請求系統調用形成的,什麼是系統調用,後面小節會舉例講)。
  • 外中斷常見的狀況如I/O中斷(由I/O控制器產生,用於發送信號通知操做完成等信號,好比進程須要請求打印機資源,打印機有一個啓動準備的過程,準備好了就會給CPU一個I/O中斷,告訴它已經準備好了)、時鐘中斷(由處理器內部的計時器產生,容許操做系統以必定規程執行函數,操做系統每過大約15ms會進行一次線程調度,就是利用時鐘中斷來實現的)。

2.5 系統調用

爲何須要系統調用?

  • 好比你的程序須要讀取文件信息,可讀取文件屬於讀取硬盤裏的數據,這個操做應該時CPU在內核態去完成的,咱們的應用程序怎麼讓CPU去幫助咱們切換到內核態完成這個工做呢,這裏就須要系統調用了

  • 這裏就引出系統調用的概念和做用。

  • 應用程序經過系統調用請求操做系統的服務。系統中的各類共享資源都由操做系通通一管理,所以在用戶程序中,凡是與資源有關的操做(如存儲分配、I/O操做、文件管理等),都必須經過系統調用的方式向操做系統提出服務請求,由操做系統代爲完成。

如下內容簡單看一下便可,系統調用的分類:

須要注意的是,庫函數系統調用容易混淆。

  • 庫是可重用的模塊 處於用戶態
  • 進程經過系統調用從用戶態進入內核態, 庫函數中有很大部分是對系統調用的封裝

舉個例子:好比windowslinux中,建立進程的系統調用方法是不同的。 但在node中的只須要調用相同函數方法就能夠建立一個進程。例如

// 引入建立子進程的模塊
const childProcess = require('child_process')
// 獲取cpu的數量
const cpuNum = require('os').cpus().length

// 建立與cpu數量同樣的子進程
for (let i = 0; i < cpuNum; ++i) {
  childProcess.fork('./worker.js')
}
複製代碼

2.6 進程的定義、組成、組織方式、狀態與轉換

2.6.1 爲何要引入進程的概念呢?
  • 早期的計算機只支持單道程序(是指全部進程一個一個排隊執行,A進程執行時,CPU、內存、I/O設備全是A進程控制的,等A進程執行完了,才換B進程,而後對應的資源好比CPU、內存這些才能換B用)。

  • 現代計算機是多道程序執行,就是同時看起來有多個程序在一塊兒執行,那每一個程序執行都須要系統分配給它資源來執行,好比CPU內存
  • 拿內存來講,操做系統要知道給A程序分配的內存有哪些,給B程序分配的內存有哪些,這些都要有小本本記錄下來,這個小本本就是進程的一部分,進程的一大職責就是記錄目前程序運行的狀態
  • 系統爲每一個運行的程序配置一個數據結構,稱爲進程控制塊(PCB),用來描述進程的各類信息(好比代碼段放在哪)。
2.6.2 進程的定義?

簡要的說,進程就是具備獨立功能的程序在數據集合上運行的過程。(強調動態性)

2.6.3 PCB有哪些組成

以下圖,分別說明一下

  • 進程標識符PID至關於身份證。是在進程被建立時,操做系統會爲該進程分配一個惟一的、不重複的ID,用於區分不一樣的進程
  • 用戶標識符UID用來表示這個進程所屬的用戶是誰。
  • 進程當前狀態和優先級下一小節會詳細介紹
  • 程序段指針是指當前進程的程序在內存的什麼地方
  • 數據段指針是指當前進程的數據在內存的什麼地方
  • 鍵盤和鼠標是指進程被分配獲得的I/O設備
  • 各類寄存器值是指好比把程序計數器的值,好比有些計算的結果算到一半,進程切換時須要把這些值保存下來。
2.6.4 進程的組織

在一個系統中,一般由數10、數百乃至數千個PCB。爲了對他們加以有效的管理,應該用適當的方式把這些PCB組織起來。這裏介紹一種組織方式,相似數據結構裏的鏈表。

2.6.5 進程的狀態

進程是程序的一次執行。在這個執行過程當中,有時進程正在被CPU處理,有時又須要等待CPU服務,可見,進程的 狀態是會有各類變化。爲了方便對各個進程的管理,操做系統須要將進程合理地劃分爲幾種狀態。

進程的三種基本狀態:

進程的另外兩種狀態:

2.6.6 進程狀態的轉換

進程的狀態並非一成不變的,在必定狀況下會動態轉換。

以上的這些進程狀態的轉換是如何實現的呢,這就要引出下一個角色了,叫`原語。

  • 原語是不可被中斷的原子操做。咱們舉一個例子看看原語是怎麼保證不可中斷的。

原語採用關中斷指令開中斷指令實現。

  • 首先執行關中斷指令
  • 而後外部來了中斷信號,不予以處理
  • 等到開中斷指令執行後,其餘中斷信號纔有機會處理。

2.6 進程的通訊

爲何須要進程間通訊呢?

由於進程是分配系統資源的單位(包括內存地址空間),所以各進程擁有的內存地址空間相互獨立。

2.6.1 進程通訊方法---共享存儲

由於兩個進程的存儲空間不能相互訪問,因此操做系統就提供的一個內存空間讓彼此都能訪問,這就是共享存儲的原理。

其中,介紹一下基於存儲區的共享。

  • 在內存中畫出一塊共享存儲區,數據的形式、存放位置都是由進程控制,而不是操做系統。
2.6.2 進程通訊方法---管道

  • 管道數據是以字符流(注意不是字節流)的形式寫入管道,當管道寫滿時,寫進程的write()系統調用將被阻塞,等待讀進程將數據取走。當讀進程將數據所有取走後,管道變空,此時讀進程的read()系統調用將被阻塞。
  • 若是沒寫滿就不容許讀。若是都沒空就不容許寫。
  • 數據一旦被讀出,就從管道中被丟棄,這就意味着讀進程最多隻能有一個。
2.6.3 進程通訊方法---消息傳遞

進程間的數據交換以格式化的消息爲單位。進程經過操做系統提供的"發送消息/接收消息"兩個原語進行數據交換。

其中消息是什麼意思呢?就好像你發QQ消息,消息頭的來源是你,消息體是你發的內容。以下圖:

接下來咱們介紹一種間接通訊的方式(很像中介者模式或者發佈訂閱模式), 以下圖:中介者是信箱,進程經過它來收發消息。

2.7 線程

爲何要引入線程呢?

  • 好比你在玩QQ的時候,QQ是一個進程,若是QQ的進程裏沒有多線程併發,那麼QQ進程就只能同一時間作一件事情(好比QQ打字聊天)
  • 可是咱們真實的場景是QQ聊天的同時,還能夠發文件,還能夠視頻聊天,這說明若是QQ沒有多線程併發能力,QQ可以的實用性就大大下降了。因此咱們須要線程,也就是須要進程擁有可以併發多個事件的能力。

引入線程後帶來的變化

3 進程的同步和互斥

同步。是指多個進程中發生的事件存在某種前後順序。即某些進程的執行必須先於另外一些進程。

好比說進程A須要從緩衝區讀取進程B產生的信息,當緩衝區爲空時,進程B由於讀取不到信息而被阻塞。而當進程A產生信息放入緩衝區時,進程B纔會被喚醒。概念如圖1所示。

互斥。是指多個進程不容許同時使用同一資源。當某個進程使用某種資源的時候,其餘進程必須等待。

好比進程B須要訪問打印機,但此時進程A佔有了打印機,進程B會被阻塞,直到進程A釋放了打印機資源,進程B才能夠繼續執行。概念如圖3所示。

3.1 信號量(瞭解概念便可)

信號量主要是來解決進程的同步互斥的,咱們前端須要瞭解,若是涉及到同步和互斥的關係(咱們編程大多數關於流程的邏輯問題,本質不就是同步和互斥嗎?)

在操做系統中,經常使用P、V信號量來實現進程間的同步互斥,咱們簡單瞭解一下一種經常使用的信號量,記錄型信號量來簡單瞭解一下信號量本質是怎樣的。(c語言來表示,會有備註)

/*記錄型信號量的定義*/
typedef struct {
    int value; // 剩餘資源
    Struct process *L // 等待隊列
} semaphore
複製代碼

意思是信號量的結構有兩部分組成,一部分是剩餘資源value,好比目前有兩臺打印機空閒,那麼剩餘資源就是2,誰正在使用打印機,剩餘資源就減1。

Struct process *L 意思是,好比2臺打印機都有人在用,這時候你的要用打印機,此時會把這個打印機資源的請求放入阻塞隊列,L就是阻塞隊列的地址。

/*P 操做,也就是記錄型信號量的請求資源操做*/
void wait (semaphore S) {
    S.value--;
    if (S.value < 0){
        block (S.L);
    }
}
複製代碼

須要注意的是,若是剩餘資源數不夠,使用block原語使進程從運行態進入阻塞態,並把掛到信號量S的等待隊列中。

/*V 操做,也就是記錄型信號量的釋放資源操做*/
void singal (semaphore S) {
    S.value++;
    if (S.value <= 0){
        wakeup (S.L);
    }
}
複製代碼

釋放資源後,若還有別的進程在等待這個資源,好比打印機資源,則使用wakeup原語喚醒等待隊列中的一個進程,該進程從阻塞態變爲繼續態。

3.2 生產者消費者問題(瞭解概念便可)

爲何要講這個呢,主要是node的流的機制,本質就是生產者消費者問題,能夠簡單的看看這個問題如何解決。

如上圖,生產者的主要做用是生成必定量的數據放到緩衝區中,而後重複此過程。與此同時,消費者也在緩衝區消耗這些數據。該問題的關鍵就是要保證生產者不會在緩衝區滿時加入數據,消費者也不會在緩衝區中空時消耗數據。

這裏咱們須要兩個同步信號量和一個互斥信號量

// 互斥信號量,實現對緩衝區的互斥訪問
semaphore mutex = 1;
// 同步信號量,表示目前還能夠生產幾個產品
semaphore empty = n;
// 同步信號量,表示目前能夠消耗幾個產品
semaphore full = 0;
複製代碼

生產者代碼以下

producer () {
    while(1) {
        // 生產一個產品
        P(empty);
        // 對緩衝區加鎖
        P(mutex);
        這裏的代碼是生產一個產品
        // 解鎖
        V(mutex);
        // 產出一個產品
        V(full);
    }
}

複製代碼

消費者代碼以下

producer () {
    while(1) {
        // 消費一個產品
        P(full);
        // 對緩衝區加鎖
        P(mutex);
        這裏的代碼是消費一個產品
        // 解鎖
        V(mutex);
        // 消費一個產品
        V(empty);
    }
}

複製代碼

4 內存的基礎知識和概念

爲何須要內存

內存是計算機其它硬件設備CPU溝通的橋樑、中轉站。程序執行前須要先放到內存中才能被CPU處理。

4.1 cpu如何區分執行程序的數據在內存的什麼地方

  • 是經過給內存的存儲單元編址實現的。(存儲單元通常是以字節爲單位)
  • 以下圖,內存的存儲單元,就像一個酒店的房間,都有編號,好比程序一的數據都在1樓,1樓1號存儲着程序裏let a = 1這段代碼。

4.2 內存管理-內存空間的分配與回收

  • 內存分配分爲連續分配非連續分配,連續分配是指用戶進程分配的必須是一個連續的內存空間

  • 這裏咱們只講連續分配中的動態分區分配

  • 什麼是動態分區分配呢,這種分配方式不會預先劃份內存分區,而是在進程裝入內存時,根據進程的大小動態地創建分區,並使分區的大小正好適合進程的須要。(好比,某計算機內存大小64MB,系統區8MB,用戶區56MB...,如今咱們有幾個進程要裝入內存,以下圖)

  • 隨之而來的問題就是,若是此時進程1使用完了,相應在內存上的數據也被刪除了,那麼空閒的區域,後面該怎麼分配(也就是說隨着進程退出,會有不少空閒的內存區域出現)

咱們講一種較爲簡單的處理方法叫空閒分區表法來解決這個問題。以下圖,右側的表格就是一個空閒分區表。

當不少個空閒分區都能知足需求時,應該選擇哪一個分區進行分配呢,例以下圖,分別有20MB10MB4MB三個空閒分區塊,如今進程5須要4MB空閒分區,改怎麼分配呢?

咱們須要按照必定的動態分區分配算法,好比有首次適應算法,指的是每次都從低地址開始查找,找到第一個能知足大小的空閒分區。還有好比最佳適應算法,指的是從空閒分區表中找到最小的適合分配的分區塊來知足需求。

連續分配缺點很明顯,大多數狀況,須要分配的進程大小,不能跟空閒分區剩下的大小徹底同樣,這樣就產生不少很難利用的內存碎片

這裏咱們介紹一種更好的空閒分區的分配方法,基本分頁存儲。以下圖

將內存空間分爲一個個大小相等的分區(好比:每一個分區4KB).每一個分區就是一個「頁框」。頁框號從0開始。

將用戶進程的地址空間分爲與頁框大小相等的一個個區域,稱爲「頁」。每一個頁也是從0開始。

5 文件管理

文件是什麼?

文件就是一組有意義的信息/數據集合。

計算機中存放了各類各樣的文件,一個文件有哪些屬性呢?文件內部的數據應該怎樣組織起來?文件之間又該怎麼組織起來?

5.1 文件的屬性

  • 文件名。即文件的名字,須要注意的是,同一目錄下不容許有重名的文件。
  • 標識符。操做系統用於區分各個文件的一種內部的名稱
  • 類型。文件的類型。
  • 位置。文件存放的路徑,同時也是在硬盤裏的位置(須要轉換成物理硬盤上的地址)
  • 建立時間、上次修改時間、文件全部者就是字面意思。
  • 保護信息。好比對這個文件的執行權限,是否有刪除文件權限,修改文件權限等等。

5.2 文件內部數據如何組織在一塊兒

以下圖,文件主要分爲有結構文件無結構文件

5.3 文件之間如何組織起來

經過樹狀結構組織的。例如windows的文件間的組織關係以下:

接下來咱們詳細的瞭解一下文件的邏輯結構

5.4 文件的邏輯結構

邏輯結構是指,在用戶看來,文件內部的數據是如何組織起來的,而「物理結構」是在操做系統看來,文件是如何保存在外存,好比硬盤中的。

好比,「線性表」就是一種邏輯結構,在用戶看來,線性表就是一組有前後關係的元素序列,如:a,b,c,d,e....

  • 「線性表」這種邏輯結構能夠用不一樣的物理結構實現,好比:順序表/鏈表順序表的各個元素在邏輯上相鄰,在物理上也相鄰:而鏈表的各個元素在物理上能夠是不相鄰的。
  • 所以,順序表能夠實現「隨機訪問」,而「鏈表」沒法實現隨機訪問。

接下來我瞭解一下有結構文件的三種邏輯結構

5.4.1 順序文件

什麼是順序文件

指的是文件中的記錄一個接一個地在邏輯上是順序排列,記錄能夠是定長變長,各個記錄在物理上能夠順序存儲鏈式存儲

  • 順序文件按結構來劃分,能夠分爲串結構順序結構
  • 串結構是指記錄之間的順序與關鍵字無關,一般都是按照記錄的時間決定記錄的順序。
  • 順序結構就必須保證記錄之間的前後順序按關鍵字排列

這裏須要注意的知識點是,順序文件的存儲方式和是否按關鍵字排列,會影響數據是否支持隨機存取是否能夠快速按關鍵字找到對應記錄的功能。

能夠看到,順序文件按順序存放對於查找是很是有幫助的,咱們在記錄文件的時候也能夠注意利用這一點。

5.4.2 索引文件

對於可變長記錄文件,要找到第i個記錄,必須先順序查找前i-1個記錄(也就是須要遍歷一遍),可是不少場景中又必須使用可變長記錄,如何解決這個問題呢?這就引出來立刻講的索引文件

  • 給這些變長的記錄都用一張索引表來記錄,一個索引表項包括了索引號長度指針

  • 其中,能夠將關鍵字做爲索引號的內容,若是關鍵字自己的排列是有序的,那麼還能夠按照關鍵字進行折半查找。這裏是關鍵,由於咱們平時用mysql數據庫對某個字段假如索引,就是這個道理。

  • 可是創建索引表的問題也很明顯,首先若要刪除/增長一個記錄,同時也要對索引表操做,其次,若是增長一條記錄才1KB,可是索引表增長i一條記錄可能有8KB,以致於索引表的體積大大多於記錄。存儲空間的利用率就比較低。

5.4.3 索引順序文件

索引順序文件是索引文件順序文件思想的結合。索引順序文件中,一樣會爲文件創建一張索引表,但不一樣的是,並非每一個記錄對應一個索引表項,而是一組記錄對應一個索引表項。

如上圖,學生記錄按照學生姓名的開頭字母進行分組。每一個分組就是一個順序文件,分組內的記錄不須要按關鍵字排序

5.5 文件目錄

首先,咱們須要瞭解一下文件控制塊是什麼。咱們假設目前在windows的D盤,以下圖

能夠看到,目錄自己就是一種有結構的文件,記錄了目錄裏的文件目錄的信息,好比名稱和類型。而這些一條條的記錄就是一個個的「文件控制塊」(FCB)

文件目錄的結構一般是樹狀的,例如linux裏/是指根路徑,/home是根路徑下的二級目錄

  • 須要注意的是,樹狀目錄不容易實現文件共享,因此在樹形目錄結構的基礎上,增長了一些指向同一節點的有向邊(能夠簡單理解爲引用關係,就跟js裏的對象同樣)
  • 也就是說須要爲每一個共享節點設置一個共享計數器,用於記錄此時有多少個地方在共享該結點。只有共享計數器減爲0,才刪除該節點。

文件分配方式(物理分配)

咱們這裏介紹一種索引分配的方式:

索引分配容許文件離散地分配在各個磁盤塊中,系統會爲每一個文件創建一張索引表,索引表記錄了文件各個邏輯塊對應的物理塊。索引表存放的磁盤塊稱爲索引快。文件數據存放的磁盤塊稱爲數據塊。

截屏2021-07-30 上午8.48.45.png

如上圖,假設某個新建立的文件'aaa'的數據依次存放磁盤塊2->5->13>9。7號磁盤塊做爲’aaa‘的索引塊,索引塊保存了索引表的內容

文件的邏輯分配和物理分配

上面咱們講到了文件的邏輯分配,是站在用戶視角的分配,物理分配是站在操做系統的角度的分配,分配的是實際的物理磁盤裏的空間。

舉個例子,咱們用戶看到的文件,意識裏都是順序排列的,好比說,excel表有100行數據,用戶看來這100行數據就是連續的。

在操做系統的視角,它能夠把這100行數據分爲一個個的數據塊,好比跟磁盤塊(假設磁盤塊是1kb大小)同樣都是1kb,拆分後的數據可使用索引表的形式分配(也就是咱們上面纔講了的,索引分配的方式,打散分配在實際的物理磁盤裏)

5.6 文件存儲空間管理

首先,咱們瞭解一下磁盤分爲目錄區文件區

接着,咱們瞭解一下常見的兩種文件存儲空間的管理算法,以下圖,假如硬盤上空閒的數據塊是藍色,非空閒的數據塊是橙色。

對分配連續的存儲空間,能夠採用空閒表法(只講這種較簡單的方法)來分配回收磁盤塊。對於分配,能夠採用首次適應,最佳適應等算法來決定要爲文件分配哪一個區間。(空閒表表示以下)

  • 首次適應是指當要插入數據的時候,空閒表會依次檢查空閒表中的表項,而後找到第一個知足條件的空閒區間。

  • 最佳適應算法是指當要插入數據的時候,空閒表會依次檢查空閒表中的表項,而後找到知足條件並且空閒塊最小的空閒區間

再講一種位示圖法

以下圖:

image.png

每個二進制位對應一個磁盤塊,好比上面0表示空閒塊,1表示已分配的塊。並且咱們能夠經過必定的公式,能夠從示圖表的橫縱座標推斷出物理塊的實際地址,也能夠從物理塊的實際地址推斷出在表裏的橫縱座標。

5.7 文件共享

文件共享分爲兩種

  • 注意,多個用戶共享同一個文件,意味着系統只有「一份」文件數據。而且只要某個用戶修改了該文件的數據,其餘用戶也能夠看到文件的變化

  • 軟鏈接能夠理解爲windows裏的快捷方式

  • 硬連接能夠理解爲js裏的引用計數,只有引用爲0的時候,纔會真正刪除這個文件。

5.8 文件保護

操做系統須要保護文件的安全,通常有以下3種方式:

  • 口令保護。是指爲文件設置一個「口令」(好比123),用戶請求訪問該文件時必須提供對應的口令。口令通常放在文件對應的FCB或者索引結點上。
  • 加密保護。使用某個"密碼"對文件進行加密,在訪問文件時須要提供正確的「密碼」才能對文件進行正確的解密。
  • 訪問控制。在每一個文件的FCB或者索引節點種增長一個訪問控制列表,該表中記錄了各個用戶能夠對該文件執行哪些操做。

總結文件系統這塊的內容

咱們舉一個實際案例,把上面的內容總結一下。

假如咱們當前的操做系統採用以下的文件系統管理方式:

  • 文件的物理結構 --- 索引分配(混合索引)
  • 文件目錄的實現 --- inode結點
  • 空閒分區管理 --- 位示圖法

那麼咱們假設0號磁盤塊就是裝載位示圖的磁盤塊,用來管理哪些磁盤是空閒的哪些是正在使用的。

由於這裏咱們已經使用了0號塊,位示圖的第一項就是1

接着咱們把磁盤塊第二塊用來放inode節點,也就是文件目錄索引節點,意思是文件目錄下存放的只有文件名和索引節點的位置,要知道文件的詳細信息,就要靠着

假設2號磁盤塊存放了咱們根目錄信息,而自己目錄其實也是一種特殊的文件,也在inode節點表裏有本身的信息,1號磁盤塊增長相似以下信息:

類型:目錄
存放在:2號磁盤塊
複製代碼

2號磁盤塊裏面存放了一個你好.txt文件,那麼2號磁盤塊會增長一行信息,相似

文件名:你好.txt
inode結點:2
複製代碼

這就意味着,2號inode節點存放了你好.txt文件的具體磁盤塊在哪,因此在1號磁盤塊的2號inode節點增長

類型:txt
存放在:三、4號磁盤塊
複製代碼

爲何要放到三、4號磁盤塊呢,由於咱們有位示圖,知道哪些磁盤塊是空閒的就分配給它,一掃描發現三、4正空閒並且知足存放這個文件的條件,就分配出去了。

咱們在細分一下這裏的三、4號磁盤塊是什麼意思,由於咱們物理磁盤塊分配的方法是混合索引,其實三、4號磁盤塊表示的形式以下:

直接索引:3號磁盤塊
直接索引:4號磁盤塊
複製代碼

上面只涉及到直接索引,咱們其實還能夠有1級索引,2級索引,這些索引指向的是一個索引表,咱們這裏就不詳細敘述了(以前交過索引塊和索引表)。

到這裏咱們們就基本明白了一個文件系統的基本運行原理。

6 I/O設備

什麼是I/O設備

I/O就是輸入輸出(Input/Output)的意思,I/O設備就是能夠將數據輸入到計算機,或者能夠接收計算機輸出數據的外部設備,屬於計算機中的硬件部件。

6.1 I/O設備分類--按使用特性

  • 人機交互類設備,這類設備傳輸數據的速度慢

  • 存儲設備,這類設備傳輸數據的速度較快

  • 網絡通訊設備,這類設備的傳輸速度介於人機交互設備和存儲設備之間

6.2 I/O控制器

CPU沒法直接控制I/O設備的機械部件,所以I/O設備還要有一個電子部件做爲CPUI/O設備機械部件之間的「中介」,用於實現CPU對設備的控制。這個電子部件就是I/O控制器

  • 接收和識別CPU發出的指令是指,好比CPU發來讀取文件的命令,I/O控制器中會有相應的控制寄存器來存放命令和參數
  • 向cpu報告設備的狀態是指,I/O控制器會有相應的狀態寄存器,用來記錄I/O設備是否空閒或者忙碌
  • 數據交換是指I/O控制器會設置相應的數據寄存器。輸出時,數據寄存器用於暫存CPU發來的數據,以後再由控制器傳送給設備。
  • 地址識別是指,爲了區分設備控制器中的各個寄存器中的各個寄存器,也須要給各個寄存器設置一個特性的「地址」。I/O控制器經過CPU提供的「地址」來判斷CPU要讀寫的是哪一個寄存器

6.3 I/O控制方式

  • 這裏咱們指講一下目前比較先進的方式,通道控制方式。

  • 通道能夠理解爲一種「弱雞版CPU」。通道能夠識別並執行一系列通道指令。

通道最大的優勢是極大的減小了CPU的干預頻率I/O設備完成任務,通道會向CPU發出中斷,不須要輪詢來問I/O設備是否完成CPU下達的任務。

本文完結。

預告:後面會有數據結構入門知識(經常使用的數據結構以及在內存的存儲形式,並對比其增刪改查的時間複雜度)

注: 本文絕大多數資料來源於如下的學習視頻資料

相關文章
相關標籤/搜索