《現代操作系統》第十章——實例研究(讀後筆記)

10.1 UNIX 與 Linux 的歷史

就當看看歷史,不記筆記了這節。

10.2 Linux 簡介

10.2.2 Linux 接口

POSIX:可移植操作系統接口

POSIX 規定庫函數的接口,而不是系統調用接口。

Linux 具有三種不同接口:系統調用接口、庫函數接口、標準應用程序構成的接口

10.2.3 shell

一個程序的標準輸入,標準輸出,標準錯誤,正常情況默認指向終端。

< 文件名:重定向標準輸入

> 文件名:重定向標準輸出

| 管道符將左邊輸出當作右邊輸入

命令後加上 & 後臺運行程序

shell 腳本:存放一系列 shell 命令,而且有一些語法規則

10.2.4 Linux 應用程序

Linux 的命令行用戶界面包含大量標準應用程序,大致分六類:

  • 文件和目錄操作命令
  • 過濾器
  • 程序設計工具,如編譯器和編輯器
  • 文檔處理
  • 系統管理
  • 其他

POSIX 規定了上述分類中主要是前三類的程序的語法和語義

10.2.5 內核結構

Linux 內核還有三個重要部件,各個部件之間相互依賴

  • I/O 部件
  • 內存管理部件
  • 進程管理部件

I/O 部件包含所有負責設備交互以及實現聯網和存儲功能的I/O的內核部件。

這些 I/O 功能整合在虛擬文件系統層中。頂層來看,對一個文件進行讀寫,不論是磁盤還是內存都是一樣的。

下面有句話沒讀懂,需要每一個鍵盤輸入 …算了不求甚解

內存管理部件包含:虛擬內存、頁面置換、頁面緩存

進程管理部件包含:信號處理、進程/線程創建終止、CPU調度

10.3 Linux 中的進程

10.3.1 基本概念

守護進程:後臺運行的特殊進程,系統啓動時守護進程就已經被 shell 腳本開啓

一個典型的守護進程『計劃任務』,每分鐘運行一次檢查是否有工作需要它完成。

fork 系統調用,創建一個與原始進程完全相同的進程副本,fork 系統調用給子進程返回零值,父進程返回子進程的進程標識符。父子進程都有自己的私有內存映像。但父進程和子進程共享已經打開的文件。

子進程想要知道自己的 PID,可以調用 getpid

進程間通信方式:管道、軟中斷

管道:兩個進程之間建立一個通道,一個進程向通道寫入字節流,另個進程從通道中讀取字節流。

管道是同步的,一個進程試圖從空的管道讀取數據,該進程會被掛起直到管道中有數據。

shell 中的管線就是用管道技術實現的。

軟中斷:一個進程給另一個進程發送信號。需要一個信號處理函數,信號到達時控制立即切換到信號處理函數。一個進程只可以給它所在『進程組』中其他進程發送信號。一個進程可以利用系統調用給它所在進程組中所有成員發送信號。

10.3.2 Linux 進程管理相關的系統調用

感覺這部分可以大致瞭解,後面再深入學習。

fork:創建子進程,子進程中返回 0,父進程返回子進程 PID

waitpid:三個參數,第一個指定等待進程,如果時 -1 任何一個子進程結束都可以;第二個參數存儲子進程退出狀態的變量地址;第三個參數沒有子進程結束,調用者是阻塞還是返回。

exec

在 fork 後的子進程中使用 exec 函數,可以裝入和運行其它程序(子進程替換原有進程,和父進程做不同的事)。

exec 函數可以根據指定的文件名或目錄名找到可執行文件,並用它來取代原調用進程的數據段、代碼段和堆棧段。在執行完後,原調用進程的內容除了進程號外,其它全部被新程序的內容替換了。

三個參數,第一個參數待執行文件名;第二個參數指向數組指針用來傳遞參數;第三個參數指向環境變量的指針

exit:進程退出時調用這個函數,傳入的參數會傳提給父進程調用 waitpid 函數的第二個參數。

如果一個進程退出但父進程沒有等待它,這個進程進入『僵死狀態』,直到父進程等待它,進程纔會結束

sigaction:可以用來查詢或設置信號處理方式

alarm:一個定時器,過一段時間發送信號

pause:將本進程掛起直到下個信號到來

10.3.3 Linux 中進程與線程的實現

每個進程一個 task_struct 的進程描述符始終存在內存中,包含內核管理全部進程所需的信息,如調度參數、已打開的文件描述符列表等。進程描述符從進程創建就一直存在內核堆棧中,Linux 還通過進程標識符(PID)區分進程。

進程描述符的信息大致分以下幾類:

  • 調度參數。進程優先級、最近消耗 CPU 時間、最近睡眠時間。
  • 內存映射。指向代碼、數據、堆棧段等的指針
  • 信號。忽略的、需要被捕捉的、暫時阻塞的、在傳遞中的。
  • 機器寄存器。內核陷阱發生時,機器寄存器的內容都會被保存
  • 系統調用狀態。當前系統調用的信息,參數,返回值
  • 文件描述符表
  • 統計數據
  • 內核堆棧
  • 其他。PID、父進程的 PID 等

進程創建過程大致理解,爲子進程創建一個新的進程描述符和用戶空間,然後從父進程複製大量內容。再賦予子進程 PID,並建立內存映射,賦予文件訪問權限,然後寄存器內容初始化準備運行。

寫時複製:創建子進程時,複製內存慢,並不直接複製,只有當進程(父子都可)進行寫入操作才複製。

Linux 線程

多進程多線程,fork 會有一堆需要解決的問題,信號量,文件等。

引入一個新的系統調用 clone。略複雜不做筆記,之後深入。

10.3.4 Linux 中的調度

Linux 線程是內核線程,Linux 系統的調度是基於線程,而不是進程的。

Linux 將線程區分爲三類:

  • 實時先入先出:最高優先級
  • 實時輪轉:有一個時間量,時間到後可以被搶佔
  • 分時

前兩類線程不是真正的實時線程,只是比分時優先級高。

實時線程優先級從 0 到 99,0 是最高優先級。非實時優先級分 100 到 139。非實時線程根據優先級分配 CPU 時間片。

每個線程被分配一個 nice 值,即『優先級調節值』。默認是 0,可以通過系統調用 nice 來修改。

接下來討論兩個 Linux 系統的調度算法。

Linux O(1) 調度器

能夠常數時間內執行任務調度。

調度隊列分成兩個數組:正在活動數組、過期失效數組

每個數組包含 140 個鏈表頭每個鏈表有不同優先級。鏈表頭指向給定優先級的雙向進程鏈表。

先對活動數組內的任務進行調度,任務時間片到期放入過期失效數組。當活動數組內沒有任務,過期失效數組變爲活動數組。

這樣保證優先級低的任務不會被餓死。不同優先級被賦予不同的時間片長度。

CPU 密集型應該優先級高,但是 Linux 事先無法確定任務類型,所以優先級需要動態的不斷被計算。根據被搶佔時間長度更改優先級。

完全公平調度器『CFS』

非實時任務的默認調度器。

思想:使用一顆紅黑樹作爲調度隊列的數據結構。根據任務在 CPU 上運行時間長度有序排列到樹中,這種時間稱爲『虛擬運行時間』。樹中每個節點對應一個任務,左側的子節點對應 CPU 上運行時間少的任務,因此左側任務更早調用。週期性的根據任務已運行時間增加虛擬運行時間值,並重新插入合適位置。

優先級低的任務虛擬運行時間值增加得更快。選擇一個節點運行 O(1),插入任務 O(logN)

Linux 調度器還包含對多處理器多核平臺有益的特性。

多處理器,每個運行隊列數據結構與一個處理器相對應,在滿足性能和親和的前提下調度器能夠加載平衡。

調度器只考慮可運行任務,可運行任務在調度隊列,其他任務在等待隊列。

每種任務可能需要等待的事件對應一個隊列,隊列頭包含指向任務鏈表的指針以及一枚自旋鎖。

Linux 系統中的同步

內存屏障:保證讀寫操作在任何後續訪問發生前已經完成。

自旋鎖、信號量、互斥量等

10.3.5 啓動 Linux 系統

啓動計算機 -> BIOS加電自檢 -> 對硬件檢測和初始化 -> 啓動磁盤第一個扇區『主引導記錄』 -> 讀入到一個固定內存區域並執行……看看就好

10.4 Linux 中的內存管理

10.4.1 基本概念

每個 Linux 進程都有一個地址空間,邏輯上由三段組成:代碼、數據、堆棧段。

代碼段包含形參可執行代碼的機器指令,通常只讀。

數據段包含程序變量、字符串、數字和其他數據的存儲。分初始化數據和未初始化數據。

棧段,從虛擬地址空間頂部或附近開始,並向低地址空間延伸。程序啓動時棧不爲空,包含了所有環境變量以及爲了調用它而向 shell 輸入的命令行。

大多 Linux 系統支持共享代碼段。

數據段和棧段不共享,除非是沒有修改頁面的父進程下的子進程。

Linux 的進程支持 『內存映射文件』來訪問文件,類似讀取內存中的數據。

下面部分草草讀過

10.4.2 Linux 中的內存管理系統調用

10.4.3 Linux 中內存管理的實現

Linux 內存由三部分組成。前兩部分是內核和內存映射,固定在內存中(頁面從不換出)。

1. 物理內存管理

四級頁表

2. 內存分配機制

第一個內存分配器

頁面分配器,分配物理內存頁框的主要機制,使用『夥伴算法』

大概意思,將頁框分爲連續的二的冪次個數個頁面塊。這樣能快速找到合適的內存塊。但是會導致碎片太多。

第二個內存分配器

爲了緩解碎片太多,另個內存分配器『slab 分配器』,使用夥伴算法得到的內存塊,切除 slab(更小的單元)進行管理。

對象緩存:因爲內核頻繁創建撤銷一定類型的對象,使用對象緩存。緩存由指向一個或多個 slab 的指針組成,slab 可以指向大量相同類型的對象。

第三個內存分配器

vmalloc:用於僅僅需要連續虛擬地址空間的請求,用於分配大量連續地虛擬地址空間。

3. 虛擬地址空間表示

10.4.4 Linux 中的分頁

分頁一部分由內核實現,一部分由『頁面守護進程』實現。

交換區:長度固定的分頁文件(應該是指這句話)

頁面置換算法

PFRA(頁框回收算法),頁面區分爲四種:

  • 不可回收:包括保留或鎖定頁面、內核態棧等,不會被換出
  • 可交換:必須在回收前寫回交換區或分頁磁盤分區
  • 可同步:如果被標記爲髒的必須寫回磁盤
  • 可丟棄:可以立即回收的

每次先回收容易回收的頁面,可丟棄和未被引用的可以立即加入空閒鏈表從而回收。接着找有備份未修改的頁面……

10.5 Linux 中的 I/O 系統

10.5.2 網絡

套接字,常用套接字類型:

  • 可靠的面向連接的字節流
  • 可靠的面向連接的數據包流
  • 不可靠的數據包傳輸

第一種,允許不同機器上兩個進程之間建立一個等同管道的連接。系統保證所有被傳送的字節都能夠到達,並按發送順序到達。

第二種,和第一種類似,不過是發送一次接收一次。第一種如果發送五次,會一次接收到所有。

第三種,高性能

10.6 Linux 文件系統

10.6.1 基本概念

獨佔鎖:指該鎖一次只能被一個線程所持有

共享鎖:指該鎖可以被多個線程鎖持有(應該是隻能一人寫,讀者不限的意思)

這塊竟然看得還挺輕鬆,文件系統很多都講了,筆記先略過大部分。

10.6.2 Linux 種的文件系統調用

creat

open

close

read

write

lseek 改變讀寫位置

stat 查看文件信息

pipe

fcntl

10.6.3 Linux 文件系統的實現

1. Linux 虛擬文件系統

虛擬文件系統『VFS』,隱藏 Linux 支持的所有文件系統之間的區別。

VFS 支持的四個主要的文件系統結構

  • Superblock,包含文件系統佈局的重要信息
  • i 節點,表示某個確切的文件,目錄和設備也被當作文件
  • Dentry,目錄項
  • File,打開文件在內存中的表示

2. Linux ext2 文件系統

磁盤被分爲許多塊組,0 號塊組通常存儲啓動計算機的代碼。

實現太複雜,草草看看過,告辭。

3. Linux ext4 文件系統

最主要相比 ext2 多了日誌文件系統,其他方面也有加強。

4. /proc 文件系統

10.6.4 NFS 網絡文件系統

網絡文件系統,就知道幹啥的,不看了。。

10.9 小結

關鍵概念,進程、內存模型、I/O 和文件系統。

我就這?太菜了,好多沒怎麼看懂就草草看過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章