計算機基礎知識

世徒 2024-04-07 10:48 14次浏览 0 条评论 taohigo.com

第一節_操作系統概述

操作系統就是軟件,直接和計算機的硬件進行交互軟件

然而,程序員不會直接和這些硬件打交道,而且每位程序員不可能會掌握所有計算機系統的細節,這樣我們就不用再編寫代碼瞭,所以在硬件的基礎之上,計算機安裝瞭一層軟件,這層軟件能夠通過響應用戶輸入的指令達到控制硬件的效果,從而滿足用戶需求,這種軟件稱之為操作系統,它的任務就是為用戶程序提供一個更好、更簡單、更清晰的計算機模型。

這是一個操作系統的簡化圖,最下面的是硬件,硬件包括芯片、電路板、磁盤、鍵盤、顯示器等我們上面提到的設備,在硬件之上是軟件。大部分計算機有兩種運行模式:內核態和用戶態,軟件中最基礎的部分是操作系統,它運行在內核態中,內核態也稱為管態和核心態,它們都是操作系統的運行狀態,隻不過是不同的叫法而已。操作系統具有硬件的訪問權,可以執行機器能夠運行的任何指令。軟件的其餘部分運行在用戶態|下。

linux 內核vs Windows內核

這個中間人就由內核來負責,讓申核作為應用連接硬件設備的橋梁,應用程序隻需關心與內核交互,不用關心硬件的細節。

內核有哪些能力呢?

現代操作系統,內核一般會提供4個基本能力:

  • 管理進程、線程,決定哪個進程、線程使用CPU,也就是進程調度的能力;·管理內存,決定內存的分配和回收,也就是內存管理的能力;
  • 管理硬件設備,為進程與硬件設備之間提供通信能力,也就是硬件通信能力;
  • 提供系統調用,如果應用程序要運行更高權限運行的服務,那麼就需要有系統調用,它是用戶程序與操作系統之間的接口。
  • 內核是怎麼工作的?

內核具有很高的權限,可以控制 cpu、內存、硬盤等硬件,而應用程序具有的權限很小,因此大多數操作系統, 把內存分成瞭兩個區域:·內核空間,這個內存空間隻有內核程序可以訪問;

·用戶空間,這個內存空間專門給應用程序使用;

用戶空間的代碼隻能訪問一個局部的內存空間,而內核空間的代碼可以訪問所有內存空間。

因此,當程序使用用戶空間時,我們常說該程序在用戶態執行,而當程序使內核空間時,程序則在內核態執行。

計算機啟動過程

當你輕輕按下計算機的啟動按鈕時,你的主板就加上電瞭。

主板一般為矩形電路板,上面安裝瞭組成計算機的主要電路系統,一般有BIOS-芯片、I/O控制芯片、鍵盤和面板控制開關接口、指示燈插接件、擴充插槽、主板及插卡的直流電源供電接插件等元件。|

在主板上,有一個東西叫ROM(Read Only Memory,隻讀存儲器)。這和咱們平常說的內存RAM(Random Acess Memory,隨機存取存儲器)不同,

咱們平時買的內存條是可讀可寫的,這樣才能保存計算結果。而ROM是隻讀的,上面早就固化瞭一些初始化的程序,也就是BIOS(Basic lmput and Output System,基本輸入輸出系統)。

如果你自己安裝過操作系統,剛啟動的時候,按某個組合鍵,顯示器會彈出一個藍色的界面。能夠調整啟動順序的系統,就是我說的 BIOS,然後我們就可以先執行它。

內核具有很高的權限,可以控制 cpu、內存、硬盤等硬件,而應用程序具有的權限很小,因此大多數操作系統,把內存分成瞭兩個區域:·內核空間,這個內存空間隻有內核程序可以訪問;

·用戶空間,這個內存空間專門給應用程序使用;

用戶空間的代碼隻能訪問一個局部的內存空間,而內核空間的代碼可以訪問所有內存空間。

因此,當程序使用用戶空間時,我們常說該程序在用戶態執行,而當程序使內核空間時,程序則在內核態執行。

然後操作系統會詢問BIOS獲取配置信息。對於每個設備來說,會檢查是否有設備驅動程序。如果沒有,則會向用戶詢問是否需要推看入CD-ROM驅動(由設備制造商提供)或者從Internet上下載。一旦有瞭設備驅動程序,操作系統會把它們加載到內核中,然後初始化表,創建所需的後臺進程並啟動登錄程序或GUI。

系統調用

你會發現,一個項目要想順暢進行,常要用到公司的各種資源,比如說蓋個公章、開個證明、申請個會議室、打印個材料等等。這裡有個兩難的權衡,一方面,資源畢竟是有限的,甚至是涉及機密的,不能由項目組濫取濫用;另一方面,就是效率,咱是一個私營企業,保證項目申請資源的時候隻跑一次,這樣才能比較高效。

為瞭平衡這一點,一方面涉及核心權限的資源,還是應該被公司嚴格把控,審批瞭才能用;另外一方面,為瞭提高效率,最好有個統一的辦事大廳,明文列出提供哪些服務,誰需要可以來申請,然後就會有回應。

在操作系統中,也有同樣的問題,例如多個進程都要往打印機上打印文件,如果隨便亂打印進程,就會出現同樣一張紙,第一行是A進程輸出的文字,第二行是B進程輸出的文字,全亂套瞭。所以,打印機的直接操作是放在操作系統內核裡面的,進程不能隨便操作。但是操作系統也提供一個辦事大廳,也就是系統調用,。

系統調用也能列出來提供哪些接口可以調用,進程有需要的時候就可以去調用。這其中,立項是辦事大廳提供的關鍵服務之一。同樣,任何一個程序要想運行起來,就需要調用系統調用,創建進程。

如果一個進程在用戶態下運行用戶程序,例如從文件中讀取數據。那麼如果想要把控制權交給操作系統控制,那麼必須執行一個異常指令或者系統調用指令。操作系統緊接著需要參數檢查找出所需要的調用進程。

然後執行系統調用,把控制權移交給系統調用下面的指令。大致來說,系統調用就像是執行瞭一個特殊的過程調用,但是隻有系統調用能夠進入內核態而過程調用則不能進入內核態。

UNIX系統調用

為瞭能夠瞭解具體的調用過程,下面我們以read方法為例來看一下調用過程。

虛擬內存

如果你是電子相關專業的,肯定在大學裡搗鼓過單片機。

單片機是沒有操作系統的,所以每次寫完代碼,都需要借助工具把程序燒錄進去,這樣程序才能跑起來。另外,單片機的CPU是直接操作內存的「物理地址」。

在這種情況下,要想在內存中同時運行兩個程序是不可能的。如果第一個程序在2000的位置寫入一個新的值,將會擦掉第二個程序存放在相同位置上的所有內容,所以同時運行兩個程序是根本行不通的,這兩個程序會立刻崩潰。

單片機是沒有操作系統的,所以每次寫完代碼,都需要借助工具把程序燒錄進去,這樣程序才能跑起來。另外,單片機的CPU是直接操作內存的「物理地址」。

我們可以把進程所使用的地址「隔離」開來,即讓操作系統為每個進程分配獨立的一套「虛擬地址」,人人都有,大傢自己玩自己的地址就行,互不幹涉。但是有個前提每個進程都不能訪問物理地址,至於虛擬地址最終怎麼落到物理內存裡,對進程來說是透明的,操作系統已經把這些都安排的明明白白瞭。

操作系統會提供一種機制,將不同進程的虛擬地址和不同內存的物理地址映射起來。

如果程序要訪問虛擬地址的時候,由操作系統轉換成不同的幼理地址,這樣不同的進程運行的時候,寫入的是不同的物理地址,這樣就不會沖突瞭。

於是,這裡就引出瞭兩種地址的概念:

·我們程序所使用的內存地址叫做虛擬內存地址(VirTual Memory Address)·實際存在硬件裡面的空間地址叫物理內存地址i Pnysica!Mermory Addressy .

操作系統引入瞭虛擬內存,進程持有的虛擬地址會通過CPU芯片中的內存管理單元〔MMU)、的映射關系,來轉換變成物理地址,然後再通過物理地址訪問內存,如下圖所示:

操作系統如何管理虛擬地址和物理地址之間的關系呢?

主要有兩種方式,分別是內存分段和內存分頁。分段是比較早提出的,我們先來看看內存分段。

分段機制下。虛擬地址和物理地址如何映射?|

分段機制下的虛擬地址由兩部分姐成,段選擇子和段內偏移量。

我們來看這樣一個例子。我現在手頭的這臺電腦,有1GB的內存。我們先啟動一個圖形渲染程序,占用瞭512MB的內存,接著啟動一個Chrome瀏覽器,占用瞭128MB內存,再啟動一個Python程序,占用瞭256MB內存,這個時候,我們關掉Chrome,於是空閑內存還有1024-512- 256 = 256MB。按理來說,我們有足夠的空間再去裝載一個200MB的程序。但是,這256MB的內存空間不是連續的,而是被分成瞭兩段128MB的內存。因此,實際情況是,我們的程序沒辦法加載進來。

當然。這個我們也有辦法解決。解決的辦法叫內存交換(Memory Swapping)

我們可以把Python程序占用的那256MB內存寫到硬盤上,然後再從硬盤上讀回來到內存裡面。不過讀回來的時候,我們不再把它加載到原來的位置,而是緊緊跟在那已經被占用瞭的512MB內存後面。這樣,我們就有瞭連續的256MB內存空間,就可以去加載一個新的200MB的程序。如果你自己安裝過Linux操作系統,你應該遇到過分配一個swap硬盤分區的問題。這塊分出來的磁盤空間,其實就是專門給Linux 操作系統進行菌存交換用的。

虛擬內存、分段,再加上內存交換,看起來似乎已經解決瞭計算機同時裝載運行很多個程序的問題。不過,你千萬不要大意,這三者的組合仍然會遇到一個性能瓶頸。硬盤的訪問速度要比內存慢很多,而每一次內存交換,我們都需要把一大段連續的內存數據寫到硬盤上。所以,如果內存交換的時候,交換的是一個很占內存空間的程序,這樣整個機器都會顯得卡頓。

為瞭解決內存分段的內存碎片和內存交換效率低的問題,就出現瞭內存分頁。

內存分頁

更進一步地,分頁的方式使得我們在加載程序的時候,不再需要一次性都把程序加載到物理內存中。我們完全可以在進行虛擬內存和物理內存的頁之間的映射之後,並不真的把頁加載到物理內存裡,而是隻有在程序運行中。需要用到對應虛擬內存頁裡面的指令和數據時,再加載到物理內存裡面去。

總結一下。對於一個內存地址轉換,其實就是這樣三個步驟;

  • 把虛擬內存地址,切分成頁號和偏移量
  • 根據頁號,從頁表裡面,查詢對應的物理頁號
  • 直接拿物理頁號,加上前面的偏移量,就得到瞭物理內存地址。

下面舉個例子。虛擬內存中的頁通過頁表映射為瞭物理內存中的頁,如下圖:

因為操作系統是可以同時運行非常多的進程的,那這不就意味著頁表會非常的龐大。

在32位的環境下,虛擬地址空間共有4GB,假設一個頁的大小是4KB(2^12),那麼就需要大約100萬(2*20)個頁,每個「頁表項」需要4個字節大小來存儲,那麼整個4GB空間的映射就需要有4B的內存來存儲頁表。

這4MB大小的頁表,看起來也不是很大。但是要知道每個進程都是有自己的虛擬地址空間的,也就說都有自己的頁表。

進程和線程

我們編寫的代碼隻是一個存儲在硬盤的靜態文件,通過編譯後就會生成二進制可執行文件,當我們運行這個可執行文件後,它會被裝載到內存中,接著CPIU會執行程序中的每一條指令,那麼這個運行中的程序,就被稱為「進程」。

我們把操作系統做某件事,抽象成一種概念,稱之為一個任務。一個進程可以對應一個任務,也可以對應多個任務。

早期的計算機隻有一個CPU,多個任務需要運行怎麼辦?需要依次排隊等待,串行執行,一個任務執行完畢,才能執行下一個。這種方式存在著明顯的弊端,假設排在前面的A任務需要執行5小時,而排後面的B任務僅需要1分鐘,那麼B任務必須等待A任務5小時完成後,才能執行,這種方式顯得極其不靈活。

後來就有瞭多任務系統,在CPU同一時間隻能處理一個任務的前提下,每個任務有一定的執行時長,比如任務A執行0.O1s,切換到任務B執行0.05s,再切換到任務C執行0.01…不斷循環。這種機制也就可以在一定程度上解決上述任務B需要長時間等待的問題。

由於CPU速度非常快,這種多個任務不斷切換,會給用戶一種任務並行執行的錯覺,這種也被稱為是偽並行調度。既然有偽並行,那麼也會有真並行。在現代計算機中,常見的CPU核數可以達到8核甚至更多,操作系統可將每一個核視為一個CPU,那麼8核CPU就可以真並行執行8個任務。

進程的狀態

那麼什麼原因會導致進程會被創建,從而生成PCB呢?常見的有以下幾種1.系統初始化

2.用戶通過系統提供的API創建新進膛3.批處理作業初始恍《什麼是批處理作業).由現有進程派生子進圖

1一個進程,因為某種原因被創建瞭,那麼它可以按照以下步驟進行一系列的初始化1.給新進程分配一個進程ID

2.分配內存空間

3.初始化PCB4.進入就隊列

偽並行雖然可以解決上述任務等待的問題,但是依然還存在一系列未解之謎:·每個任務應該執行多長時間?

1.有些任務涉及瞭資源操作,執行到一半,切換任務,那麼這些資源怎麼辦?

為瞭解決上面一系列謎題,我們需要一種模型對任務進行詳盡的描述記錄。

那麼什麼原因會導致進程會被創建,從而生成PCB呢?常見的有以下幾種

1.系統初始化

2.用戶通過系統提供的API創建新進程3.批處理作業初始化(什麼是批處理作業)4.由現有進程派生子進程

一個進程,因為某種原因被創建瞭,那麼它可以按照以下步驟進行一系列的初始化1.給新進程分配一個進程ID

2.分配內存空間

3.初始化PCB4.進入就緒隊列

進程控制結構

對於一個被執行的程序,操作系統會為該程序創建一個進程。進程作為一種抽象概念,可將其視為一個容器,該容器聚集瞭相關資源,包括地址空間,線程,打開的文件,保護許可等。而操作系統本身是一個程序,有一句經典的話(程序=算法+數據結構,因此對於單個進程,可以基於一種數據結構來表示它,這種數據結構稱之為進程控制塊(PCB)

PCB是進程存在的唯一標識,這意味著一個進程的存在,必然會有一個PCB,如果進程消失瞭,那麼PCB也會隨之消失。

通常是通過鏈表的方式進行組織,把具有相同狀態的進程鏈在一起,組成各種隊列。比如:·將所有處於就緒狀態的進程鏈在一起,稱為就緒隊列;

把所有因等待某事件而處於等待狀態的進程鏈在一起就組成各種阻塞隊列;

另外,對於運行隊列在單核CPU系統中則隻有一個運行指針瞭,因為單核CPU在某個時間,隻能運行一個程序。那麼,就緒隊列和阻塞隊列鏈表的組織形式如下圖:

進程的切換

當一個正在運行中的進程被中斷,操作系統指定另一個就緒態的進程進入運行態,這個過程就是進程切換,也可以叫上下文切換。該切換過程一般涉及以下步驟:

1.保存處理器上下文環境:將CPU程序計數器和寄存器的值保存到當前進程的私有堆棧裡

⒉.更新當前進程的PCB(包括狀態更變)

3.將當前進程移到就緒隊列或者阻塞隊列

4.根據調度算法,選擇就緒隊列中一個合適的新進程,將其更改為運行態5.更新內存管理的數據結構

6.新進程內對堆棧所保存的上下文信息載入到CPU的寄存器和程序計數器,占有CPU

發生進程上下文切換有哪些場景?

·為瞭保證所有進程可以得到公平調度,CFU時間被劃分為一段段的時間片,這些時間片再被輪流分配給各個進程。這樣,當某個進程的時間片耗盡瞭,就會被系統掛起切換到其它正在等待CPU的進程運行;

·進程在系統資源不足(比如內存不足)時,要等到資源滿足後才可以運行,這個時候進程也會被掛起,並由系統調度其他進程運行;·當進程通過睡眠函數sleep這樣的方法將自己主動掛起時,自然也會重新調度;

當有優先級更高的進程運行時,為瞭保證高優先級進程的運行,當前進程會被掛起,由高優先級進程來運行;。發生硬件中斷時,CPU上的進程會被中斷掛起,轉而執行內核中的中斷服務程序;

4.根據調度算法,選擇就緒隊列中一個合適的新進程,將其更改為運行態5.更新內存管理的數據結構

6.新進程內對堆棧所保存的上下文信息載入到CPU的寄存器和程序計數器,占有CPU

線程

在早期的操作系統中都是以進程作為獨立運行的基本單位,直到後面,計算機科學傢們又提出瞭更小的能獨立運行的基本單位,也就是線程。

什麼是線程?

線程是進程當中的一條執行流程。

同一個進程內多個線程之間可以共享代碼段、數據段、打開的文件等資源,但每個線程各自都有一套獨立的寄存器和棧,這樣可以確保線程的控制流是相對獨立的。

我們一開始提及過,操作系統底層存在調度程序,調度程序可調度任務,而單線程進程,每個講程可以對應一個任務、現在,對於多線程的進程,每一個線程最終對於調度程序來說,都是一個任務,如下圖(Linux系統)。因此也有一種流行的說法線程是CPU調度的基本單位

進程間通信

操作系統管理各種應用程序的運行,創建一個一個線程管理起來。

每個選程的用戶地址空間都是獨立的,一般而自是不能互相訪問的,但內核空間是每個進程都共享的,所以進程之間要通信必須通過內核。

進程間通信目的—股有共享數據,數據傳輸,消息通知,進程控制等。以Unix/Linux 為例,介紹幾種重要的進程間通信方式:共享內存,管道,消息隊列,信號量。

管道

消息隊列

前面說到管道的通信方式是效率低的,因此管道不適合進程間頻繁地交換數據。

對於這個問題,消息隊列的通信模式就可以解決。比如,A進程要給B進程發送消息,A進程把數據放在對應的消息隊列後就可以正常返回瞭,8B進程需要的時候再去瀆取數據就可以瞭。同理,B進程要給A進程發送消息也是如此。

再來,消息隊列是保存在內核中的消息鏈表,在發送數據時,會分成一個一個獨立的數據單元,也就是消息體〈(數據塊),消息體是用戶自定義的數據類型,消息的發送方和接收方要約定好消息體的數據類型,所以每個消息體都是固定大小的存儲塊,不像管道是無格式的字節流數據。如果進程從消息隊列中讀取瞭消息體,內核就會把這個消息體刪除。

再來,消息隊列是保存在內核中的消息鏈表,在發送數據時,會分成一個一個獨立的數據單元,也就是消息體(數據塊)),消息體是用戶自定義的數據類型,消息的發送方和接收方要約定好消息體的數據類型,所以每個消息體都是固定大小的存儲塊,不像管道是無格式的字節流數據,如果進程從消息隊列中讀取瞭消息體,內核就會把這個消息體刪除。

消息隊列生命周期隨內核,如果沒有釋放消息隊列或者沒有關閉操作系統,消息隊列會一直存在,而前面提到的匿名管道的生命周期,是隨進程的創建而建立,隨進程的結束而銷毀。

缺點:

消息隊列通信討程中,存在用白態與內核態之間的數據拷貝開銷。因為進程寫入數據到內核中的消總隊列時,會發生從用戶態拷貝數據到內核態的過程,同理另一進程讀取內核中的消息數據時,會發生從內核態拷貝數據到用戶態的過程。

共享內存

信號量

通信三要素:協議,IP地址,端口

文件系統

組織形式,磁盤有磁頭、磁道。

一切皆文件

層級關系

虛擬文件系統

文件的物理結構

文件塊

空閑空間的管理

設備管理

鍵盤可以說是我們最常使用的輸入硬件設備瞭,但身為程序員的你,你知道「鍵盤敲入A字母時,操作系統期間發生瞭什麼嗎」?

設備管理器

我們的電腦設備可以接非常多的輸入輸出設備,比如鍵盤、鼠標、顯示器、網卡、硬盤、打印機、音響等等,每個設備的用法和功能都不同,那操作系統是如何把這些輸入輸出設備統一管理的呢?

為瞭屏蔽設備之間的差異,每個設備都有一個叫設備控制器(Device Control)的組件,比如硬盤有硬盤控制器、顯示器有視頻控制器等。

因為這些控制器都很清楚的知道對應設備的用法和功能,所以CPU是通過設備控制器來和設備打交道的。

設備控制器裡有芯片,它可執行自己的邏輯,也有自己的寄存器,用來與CPU進行通信,比如:

  • 通過寫入這些寄存器,操作系統可以命令設備發送數據、接收數據、開啟或關閉,或者執行某些其他操作。
  • 通過讀取這些寄存器,操作系統可以瞭解設備的狀態,是否準備好接收一個新的命令等

實際上,控制器是有三類寄存器,它們分別是狀態寄存器(Status Register)、命令寄存器(Command Register)以及數據寄存器(Data Register)

塊設備:鼠標、USB

I/O控制方式

設備驅動程序

通用塊層

網絡系統

一臺機器將自己想要表達的內容,按照某種約定好的格式發送出去,當另外一臺機益收到這些信息後,也能夠按照約定趕的格式解析出來,從而準確、可靠地獲得發送方想要表達的內容。這種約定好的格式就是網絡協議。

發送數據包