操作系統:三個簡單的部分。 第 1 部分:介紹(翻譯)

操作系統簡介

嘿哈布爾! 我想向您介紹一系列文章 - 我認為有趣的文獻 - OSTEP 的翻譯。 本材料相當深入地討論了類 UNIX 操作系統的工作,即使用進程、各種調度程序、內存和構成現代操作系統的其他類似組件。 您可以在這裡查看所有材料的原件 這裡. 請注意,翻譯是非專業的(相當隨意),但我希望我保留了一般意思。

關於這個主題的實驗室工作可以在這裡找到:
- 原來的: page.cs.wisc.edu/~remzi/OSTEP/Homework/homework.html
- 原來的: github.com/remzi-arpacidusseau/ostep-code
- 我個人的改編: github.com/bykvaadm/OS/tree/master/ostep

您也可以查看我的頻道 電報 =)

程序運行

程序運行時會發生什麼? 一個正在運行的程序只做一件簡單的事情——它執行指令。 每秒,處理器從 RAM 中檢索數百萬甚至可能數十億條指令,然後對它們進行解碼(例如,它識別這些指令屬於什麼類型)並執行它們。 這可能是將兩個數字相加、訪問內存、檢查條件、跳轉到函數等。 執行一條指令後,處理器繼續執行另一條指令。 一條條指令接一條指令執行,直到程序結束。
這個例子自然被認為是簡化的——事實上,為了加速處理器,現代硬件允許你不按順序執行指令、計算可能的結果、同時執行指令,以及類似的技巧。

馮諾依曼計算模型

我們描述的簡化工作形式類似於馮諾依曼計算模型。 馮諾依曼是計算機系統的先驅之一,他也是博弈論的創始人之一. 在程序運行的過程中,會發生一堆其他的事件,很多其他的進程和第三方邏輯在工作,其主要目的是為了簡化系統的啟動、運維。
有一組軟件負責使程序易於運行(甚至允許多個程序同時運行),允許程序共享相同的內存,並與不同的設備進行通信。 這樣的一套軟件(軟件)本質上稱為操作系統,其任務包括監控系統是否正確有效地工作,以及確保該系統易於管理。

操作系統

操作系統,簡稱OS,是一組相互關聯的程序,旨在管理計算機資源和組織用戶與計算機的交互。.
操作系統首先通過最重要的技術實現其有效性——技術 虛擬化. 操作系統與物理資源(處理器、內存、磁盤等)交互,並將其轉化為更通用、更強大、更易於使用的自身形式。 因此,為了大體的理解,可以非常粗略地將操作系統比作虛擬機。
為了允許用戶向操作系統下達命令,從而使用虛擬機的能力(如運行程序、分配內存、訪問文件等),操作系統提供了一些接口,稱為 API (應用程序編程接口),您可以對其進行調用(調用)。 一個典型的操作系統允許進行數百個系統調用。
最後,由於虛擬化允許多個程序同時運行(從而共享 CPU),同時訪問它們的指令和數據(從而共享內存),訪問磁盤(從而共享 I/O 設備),操作系統也被稱為資源管理器。 每個處理器、磁盤和內存都是系統的一種資源,因此操作系統的角色之一變成了管理這些資源的任務,高效、誠實地進行管理,反之亦然,這取決於操作系統的任務被設計。

CPU虛擬化

考慮以下程序:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

操作系統:三個簡單的部分。 第 1 部分:介紹(翻譯)

它不執行任何特殊操作,事實上,它所做的只是調用一個函數 (),其任務是循環時間檢查,一秒後返回。 因此,它無限期地重複用戶作為參數傳遞的字符串。
讓我們運行這個程序並將字符“A”作為參數傳遞給它。 結果並不是特別有趣——系統只是執行一個週期性顯示字符“A”的程序。
現在讓我們試試當同一個程序的許多實例運行時的選項,但輸出不同的字母以使其更清楚。 在這種情況下,結果會有些不同。 儘管我們只有一個處理器,但程序是同時執行的。 它是如何發生的? 但事實證明,操作系統並非沒有硬件功能的幫助,而是產生了一種錯覺。 系統具有多個虛擬處理器的錯覺,將單個物理處理器變成理論上無限的數量,從而允許看似程序同時運行。 這種錯覺被稱為 CPU虛擬化.
這張圖提出了很多問題,比如,如果要同時運行幾個程序,啟動哪個? 操作系統的“策略”負責這個問題。 策略在操作系統中有很多地方用到,回答這樣的問題,是操作系統實現的基本機制。 因此操作系統的角色是資源管理器。

內存虛擬化

現在讓我們看看內存。 現代系統中內存的物理模型表示為字節數組。. 要從內存中讀取,您需要指定 小區地址訪問它。 要寫入或更新數據,您還必須指定數據和寫入數據的單元格地址。
內存訪問在程序中不斷發生。 程序將其整個數據結構存儲在內存中,並通過執行各種指令來訪問它。 與此同時,這些指令也存儲在內存中,因此對於下一條指令的每個請求也會訪問它。

malloc() 調用

考慮下面的程序,它使用調用分配一個內存區域 malloc() (https://youtu.be/jnlKRnoT1m0):

操作系統:三個簡單的部分。 第 1 部分:介紹(翻譯)

該程序做了幾件事。 首先,它分配一些內存(第 7 行),然後打印分配的單元格的地址(第 9 行),將零寫入分配內存的第一個槽。 接下來,程序進入一個循環,在該循環中它遞增存儲在內存中“p”變量地址處的值。 它還打印自己的進程 ID。 每個正在運行的進程的進程ID都是唯一的. 啟動多個副本後,我們會偶然發現一個有趣的結果:在第一種情況下,如果您什麼都不做,只是運行多個副本,那麼地址將會不同。 但這不屬於我們的理論! 正確,因為現代發行版默認啟用內存隨機化。 如果它被禁用,我們會得到預期的結果——兩個同時運行的程序的內存地址將匹配。

操作系統:三個簡單的部分。 第 1 部分:介紹(翻譯)

結果表明,兩個獨立的程序使用自己的私有地址空間工作,而這些地址空間又由操作系統映射到物理內存中. 因此,在一個程序中使用內存地址不會以任何方式影響其他程序,而且在每個程序看來,它都有自己的一塊物理內存,完全是給它的。 然而,實際情況是物理內存是由操作系統管理的共享資源。

一致性

操作系統中的另一個重要主題是 一致性. 當談論在同一程序中同時處理許多事情時可能發生的系統問題時使用該術語。 甚至在操作系統本身內部也會出現一致性問題。 在前面的內存和處理器虛擬化示例中,我們意識到操作系統同時管理許多事情——它啟動第一個進程,然後啟動第二個,依此類推。 事實證明,這種行為會導致一些問題。 因此,例如,現代多線程程序會遇到這樣的困難。

考慮以下程序:

操作系統:三個簡單的部分。 第 1 部分:介紹(翻譯)

main 函數中的程序使用調用創建了兩個線程 pthread_create(). 在這個例子中,線程可以被認為是與其他函數一起在同一內存空間中運行的函數,顯然不止一個函數同時運行。 在這個例子中,每個線程啟動並執行函數 worker() 反過來簡單地增加變量,.

讓我們用參數 1000 運行這個程序。您可能已經猜到,結果應該是 2000,因為每個線程都會將變量遞增 1000 次。 然而,一切並沒有那麼簡單。 讓我們嘗試以一個數量級的重複次數運行該程序。

操作系統:三個簡單的部分。 第 1 部分:介紹(翻譯)

通過輸入一個數字,例如 100000,我們希望看到輸出為數字 200000。但是,如果我們多次運行 100000 這個數字,我們不僅不會看到正確答案,還會得到不同的錯誤答案。 答案在於,要增加數字,需要三個操作——從內存中提取數字,遞增,然後將數字寫回。 由於所有這些指令都不是自動執行的(所有同時執行),因此可能會發生這種奇怪的事情。 這個問題在編程中叫做 競爭條件. 當未知力量在未知時刻影響您的任何操作的性能時。

來源: www.habr.com

添加評論