Linux工作原理1簡介

来源:https://www.cnblogs.com/testing-/archive/2023/05/27/17436233.html
-Advertisement-
Play Games

要使用 `systemctl` 啟動單個服務,其中包含多個進程,你可以使用 Systemd 的 `template` 機制。以下是使用 Systemd 'template' 以創建一個可同時啟動多個進程的服務單元文件的過程: 1. 為你的服務創建一個 template 服務單元文件。服務單元文件通常 ...


乍一看,Linux是非常複雜的,有許多令人眼花繚亂的部件同時運行和通信。例如網路伺服器可以與資料庫伺服器對話,而資料庫伺服器又可以使用許多其他程式使用的共用庫。所有這些是如何運作的,以及你如何能夠理解其中的任何內容?

理解操作系統如何工作的最有效方法是通過抽象--即你可以忽略構成你試圖理解的部分的大多數細節,而專註於其基本目的和操作。例如,當你乘坐汽車時,你通常不需要考慮諸如固定汽車內部馬達的安裝螺栓或建造和維護汽車行駛道路的人等細節。你真正需要知道的是汽車的作用(把你運送到別的地方)和一些關於如何使用它的基本知識(如何操作車門和安全帶)。

如果你只是乘客,這種抽象程度管用。但如果你還需要駕駛它,你就必須深入挖掘,把你的抽象概念分成幾個部分。你現在把你的知識擴展到三個方面:汽車本身(比如它的尺寸和性能),如何操作控制裝置(方向盤、加速踏板等),以及道路的特點。

當你試圖尋找和修複問題時,抽象化有很大的幫助。例如,假設你正在駕駛汽車,行駛過程中很不順利。你可以快速評估剛纔提到的三個與汽車相關的基本抽象,以確定問題的來源。如果前兩個抽象概念(你的車或你的駕駛方式)都不是問題,那麼排除這兩個抽象概念應該相當容易,這樣你就可以把問題縮小到道路本身。你可能會發現,道路是顛簸的。現在,如果你願意,你可以更深入地挖掘你對道路的抽象,找出道路惡化的原因,或者,如果道路是新的,為什麼建築工人做了糟糕的工作。

軟體開發人員在構建操作系統及其應用程式時,將抽象作為工具。在電腦軟體中,有許多抽象的細分術語--包括子系統、模塊和包--但我們在本章將使用組件這個術語,因為它很簡單。在構建一個軟體組件時,開發人員通常不會過多考慮其他組件的內部結構,但他們會考慮他們可以使用的其他組件(這樣他們就不必再編寫任何額外的不必要的軟體)以及如何使用它們。

本章對構成Linux系統的組件作了高層次的概述。儘管每個組件的內部構成都有大量的技術細節,但我們將忽略這些細節,而專註於這些組件對整個系統的作用。我們將在隨後的章節中研究這些細節。

1.1 Linux系統中的抽象級別和層數

使用抽象將計算系統分割成組件,使事情更容易理解,但沒有組織也不行。我們將組件排列成層或級別,根據組件在用戶和硬體之間的位置,對組件進行分類(或分組)。網路瀏覽器、游戲等位於頂層;在底層,我們有電腦硬體中的記憶體--0和1。操作系統占據了中間的許多層。

Linux系統有三個主要層次。圖1-1顯示了這些層次和每個層次中的一些組件。硬體處於底層。硬體包括記憶體以及一個或多個中央處理單元(CPU),用於執行計算和從記憶體讀寫。磁碟和網路介面等設備也是硬體的一部分。

下一個層次是內核,它是操作系統的核心。內核是駐留在記憶體中的軟體,它告訴CPU去哪裡尋找下一個任務。內核作為中介,管理硬體(尤其是主記憶體),是硬體和任何運行程式之間的主要介面。

進程--由內核管理的運行程式--共同構成了系統的上層,稱為用戶空間。(進程的一個更具體的術語是用戶進程,不管用戶是否直接與該進程進行交互。例如,所有的網路伺服器都作為用戶進程運行)。
image

圖1-1:一般的Linux系統組織

內核和用戶進程的運行方式有一個重要區別:內核在內核模式下運行,而用戶進程在用戶模式下運行。在內核模式下運行的代碼可以不受限制地訪問處理器和主記憶體。這是強大但危險的特權,允許內核輕易地破壞和崩潰整個系統。只有內核可以訪問的記憶體區域被稱為內核空間。

相比之下,用戶模式限制了對(通常是相當小的)記憶體子集的訪問和CPU的安全操作。用戶空間指的是用戶進程可以訪問的主記憶體的部分。如果進程犯了錯誤而崩潰,其後果是有限的,可以由內核來清理。這意味著,如果你的網路瀏覽器崩潰了,它可能不會使已經在後臺運行了幾天的科學計算崩潰。

理論上用戶進程失控不會對系統的其他部分造成嚴重損害。在現實中,這取決於你認為什麼是 "嚴重破壞",以及進程的特定許可權,因為有些進程被允許做得比其他進程多。例如,用戶進程可以完全破壞磁碟上的數據嗎?如果有許可權,可以,而且這是相當危險的。然而,有一些保障措施來防止這種情況,大多數進程根本不允許以這種方式進行破壞。

註意
Linux內核可以運行內核線程,它們看起來很像進程,但可以訪問內核空間,比如kthreadd和kblockd。

1.2 硬體: 瞭解主記憶體

在電腦系統的所有硬體中,主記憶體可能是最重要的。在其最原始的形式中,主記憶體只是大的存儲區,用於存儲一堆0和1。每個0或1的插槽被稱為比特。這就是運行中的內核和進程所在的地方--它們只是大量的比特集合。所有來自外圍設備的輸入和輸出都流經主記憶體,也是一堆比特。CPU只是記憶體的一個操作者;它從記憶體中讀取指令和數據,並將數據寫回記憶體。

在提到記憶體、進程、內核和電腦系統的其他部分時,你會經常聽到狀態這個詞。嚴格說來,狀態是特定的比特排列。例如,如果你的記憶體中有四個比特,0110、0001和1011代表三種不同的狀態。

當你考慮到進程可以很容易地由記憶體中的數百萬比特組成時,在談論狀態時,使用抽象的術語往往更容易。與其用比特來描述一態,不如用比特來描述一個東西在這一刻已經做了什麼或正在做什麼。例如,你可以說,"該進程正在等待輸入 "或 "該進程正在執行其啟動的第二階段"。

註意:因為人們通常用抽象的術語而不是實際的比特來指代狀態,所以術語image指的是比特的特定物理排列。

1.3 內核

為什麼我們要討論主存和狀態?內核所做的一切幾乎都是圍繞著主存展開的。內核的任務之一是將記憶體分割成許多子區,它必須在任何時候都保持這些子區的某些狀態信息。每個進程都有自己的記憶體份額,而內核必須確保每個進程都保持自己的份額。

內核負責管理四個一般系統領域的任務:

  • 進程 內核負責確定哪些進程被允許使用CPU。
  • 記憶體 內核需要跟蹤所有的記憶體--哪些是當前分配給特定進程的,哪些可能是進程間共用的,哪些是空閑的。
  • 設備驅動程式 內核作為硬體(如磁碟)和進程之間的介面。通常內核的工作是操作硬體。
  • 系統調用和支持 進程通常使用系統調用來與內核通信。
    現在我們將簡要地探討這些領域的每一個問題。

註意
如果你對內核的詳細工作原理感興趣,有兩本好的教科書:《Operating System Concepts》第10版,作者是Abraham Silberschatz、Peter B. Galvin和Greg Gagne(Wiley,2018);《Modern Operating Systems》第4版,作者是Andrew S. Tanenbaum和Herbert Bos(Prentice Hall,2014)。

1.3.1 進程管理

進程管理描述了進程的啟動、暫停、恢復、調度和終止。啟動和終止進程背後的概念是相當直接的,但描述進程在正常運行過程中如何使用CPU就比較複雜了。

在任何現代操作系統上,許多進程都是 "同時 "運行的。例如,你可能在一臺台式電腦上同時打開網路瀏覽器和電子錶格。然而,事情並不像他們所看到的那樣:這些應用程式背後的進程通常不會完全在同一時間運行。

考慮單核CPU的系統。許多進程可能能夠使用CPU,但在任何時候只有一個進程能夠實際使用CPU。在實踐中,每個進程使用CPU一小部分時間,然後暫停;然後另一個進程使用CPU另一小部分時間;然後另一個進程輪流使用,如此反覆。一個進程將CPU的控制權交給另一個進程的行為被稱為上下文切換。

每一塊時間被稱為一個時間片,為進程提供足夠的時間進行重要的計算(事實上,進程經常在一個時間片內完成其當前任務)。然而,由於時間片非常小,人類無法感知它們,而且系統似乎在同時運行多個進程(一種被稱為多任務的能力)。

內核負責上下文切換。為了理解它是如何工作的,讓我們想想這樣一種情況:進程在用戶模式下運行,但它的時間片已經到了。這就是發生的情況:

  • CPU(實際的硬體)根據一個內部計時器中斷當前進程,切換到內核模式,並將控制權交還給內核。
  • 內核記錄了CPU和記憶體的當前狀態,這對於恢復剛剛被中斷的進程至關重要。
  • 內核執行在前一個時間片中可能出現的任何任務(比如從輸入和輸出(I/O)操作中收集數據)。
  • 內核現在已經準備好讓另一個進程運行。內核分析準備運行的進程列表並選擇一個。
  • 內核為這個新進程準備好記憶體,然後為CPU做準備。
  • 內核告訴CPU新進程的時間片將持續多長時間。
  • 內核將CPU切換到用戶模式,並將CPU的控制權交給該進程。

上下文切換回答了內核何時運行這一重要問題。答案是,在上下文切換期間,它在進程的時間片之間運行。

在多CPU系統的情況下,就像目前大多數機器一樣,事情變得稍微複雜一些,因為內核不需要放棄對當前CPU的控制,就可以讓一個進程在不同的CPU上運行,而且一次可以運行不止一個進程。然而,為了最大限度地利用所有可用的CPU,內核通常會執行這些步驟(並可能使用某些技巧來為自己多爭取一點CPU時間)。

1.3.2 記憶體管理

內核必須在上下文切換期間管理記憶體,這可能是一項複雜的工作。以下條件必須成立:

  • 內核必須在記憶體中擁有自己的私有區域,用戶進程不能訪問。
  • 每個用戶進程都需要自己的記憶體區域。
  • 用戶進程不能訪問另一個進程的私有記憶體。
  • 用戶進程可以共用記憶體。
  • 用戶進程中的一些記憶體可以是只讀的。
  • 系統可以通過使用磁碟空間作為輔助來使用比實際存在的更多的記憶體。

現代CPU包括一個記憶體管理單元(MMU memory management unit ),它可以實現一種叫做虛擬記憶體的記憶體訪問方案。當使用虛擬記憶體時,進程並不直接通過其在硬體中的物理位置來訪問記憶體。相反,內核將每個進程設置成好像它自己有一整台機器的樣子。當進程訪問它的一些記憶體時,MMU會攔截訪問,並使用記憶體地址圖將記憶體位置從進程的角度轉換為機器中的實際物理記憶體位置。內核仍然必須初始化並持續維護和改變這個記憶體地址圖。例如,在上下文切換過程中,內核必須將該地圖從離開的進程改變為進入的進程。

註意: 記憶體地址映射的實現被稱為頁表。

你將在第8章中瞭解更多關於如何查看記憶體性能的信息。

1.3.3 設備驅動和管理

內核對設備的作用相對簡單。設備通常只能在內核模式下訪問,因為不適當的訪問(比如用戶進程要求關閉電源)會使機器崩潰。值得註意的困難是,不同的設備很少有相同的編程介面,即使這些設備執行相同的任務(例如,兩個不同的網卡)。因此,設備驅動歷來是內核的一部分,它們努力為用戶進程提供統一的介面,以簡化軟體開發者的工作。

系統調用和支持

還有一些其他類型的內核功能可供用戶進程使用。例如,系統調用(或稱syscalls)執行一些特定的任務,而這些任務單靠用戶進程是不能很好地完成的,或者根本就不能完成。例如,打開、讀取和寫入文件的行為都涉及系統調用。

兩個系統調用,fork()和exec(),對於理解進程如何啟動很重要:

fork() 當進程調用fork()時,內核會創建一個幾乎相同的進程副本。
exec() 當一個進程調用exec(program)時,內核載入並啟動程式,取代當前進程。

除了init(見第6章),Linux系統中所有新的用戶進程都是由於fork()而啟動的,大多數時候,你也會運行exec()來啟動一個新的程式,而不是運行一個現有進程的副本。非常簡單的例子是你在命令行上運行的任何程式,例如顯示一個目錄內容的ls命令。當你在終端視窗中輸入ls時,在終端視窗中運行的shell調用fork()來創建一個shell的副本,然後這個shell的新副本調用exec(ls)來運行ls。圖1-2顯示了啟動像ls這樣的程式的進程和系統調用的流程。

image

圖1-2: 啟動一個新的進程

註意
系統調用通常用括弧來表示。在圖1-2所示的例子中,要求內核創建另一個進程的進程必須執行fork()系統調用。這個符號來自於C語言中調用的寫法。你不需要知道C語言來理解本書,只要記住系統調用是進程和內核之間的交互。此外,本書還簡化了某些組的系統調用。例如,exec()指的是整個系統調用家族,它們都執行類似的任務,但在編程上有所不同。還有一個稱為線程的進程的變種,我們將在第8章中介紹。

內核還支持具有傳統系統調用以外的功能的用戶進程,其中最常見的是偽設備(pseudodevices)。偽設備對用戶進程來說看起來像設備,但它們是純粹用軟體實現的。這意味著它們在技術上不需要在內核中出現,但它們通常出於實際原因而出現。例如,內核的隨機數生成器設備(/dev/random)就很難在用戶進程中安全實現。

註意:從技術上講,訪問偽設備的用戶進程必須使用系統調用來打開設備,所以進程不能完全避免系統調用。

1.4 用戶空間

如前所述,內核為用戶進程分配的主記憶體被稱為用戶空間。因為進程只是記憶體中的一個狀態(或image),所以用戶空間也指整個運行中的進程集合的記憶體。(你也可能聽到用更非正式的術語userland來表示用戶空間;有時這也意味著在用戶空間運行的程式。)

Linux系統中的大部分實際操作都發生在用戶空間。儘管從內核的角度來看,所有的進程本質上是平等的,但它們為用戶執行不同的任務。對於用戶進程所代表的系統組件的種類,有基本的服務級別(或層)結構。圖1-3顯示了一組組件在Linux系統中是如何配合和互動的。基本服務在最底層(最接近內核),實用服務在中間,而用戶接觸的應用程式在最上面。圖1-3是一個大大簡化的圖,因為只顯示了六個組件,但是你可以看到頂部的組件是最接近用戶的(用戶界面和網路瀏覽器);中間層的組件包括網路瀏覽器使用的功能變數名稱緩存伺服器;底部還有幾個較小的組件。

image

底層往往由小的組件組成,執行單一的、不複雜的任務。中間層有較大的組件,如郵件、列印和資料庫服務。最後,頂層的組件執行複雜的任務,用戶經常直接控制。組件也使用其他組件。一般來說,如果一個組件想使用另一個組件,第二個組件要麼處於同一服務級別,要麼低於這個級別。

然而,圖1-3只是對用戶空間安排的近似描述。在現實中,用戶空間並沒有什麼規則。例如,大多數應用程式和服務都會寫被稱為日誌的診斷信息。大多數程式使用標準的syslog服務來寫日誌信息,但有些程式喜歡自己做所有的日誌。

此外,對一些用戶空間的組件也很難進行分類。伺服器組件,如Web和資料庫伺服器,可以被認為是非常高級的應用程式,因為它們的任務往往很複雜,所以你可能會把這些放在圖1-3的最高層。然而,用戶應用程式可能依賴於這些伺服器來執行他們不願自己做的任務,所以你也可以為把它們放在中間層提供理由。

1.5 用戶

Linux內核支持Unix用戶的傳統概念。用戶是可以運行進程和擁有文件的實體。用戶通常與用戶名相關聯,例如,系統可以有名為billyjoe的用戶。然而,內核並不管理用戶名;相反,它通過簡單的數字標識符(稱為用戶ID)來識別用戶。(你將在第7章中瞭解更多關於用戶名與用戶ID的對應關係)。

用戶的存在主要是為了支持許可權和邊界。每個用戶空間的進程都有一個用戶所有者,而進程據說是作為所有者運行的。用戶可以終止或修改自己進程的行為(在一定範圍內),但它不能幹擾其他用戶的進程。此外,用戶可以擁有文件,並選擇是否與其他用戶分享這些文件。

Linux系統除了對應於使用該系統的真實人類的用戶外,通常還有一些用戶。你將在第三章中詳細瞭解這些用戶,但最重要的用戶是root。root用戶是前述規則的一個例外,因為root可以終止和改變其他用戶的進程,並訪問本地系統中的任何文件。由於這個原因,root被稱為超級用戶。在傳統的Unix系統中,能夠以root身份操作的人,也就是有root許可權的人,就是管理員。

註意:以root身份操作可能是危險的。因為系統會讓你做任何事情,即使它對系統有害,也很難識別和糾正錯誤。出於這個原因,系統設計者不斷嘗試使root許可權儘可能不被需要--例如,不需要root許可權就可以在筆記本上切換無線網路。此外,儘管root用戶很強大,但它仍然運行在操作系統的用戶模式,而不是內核模式。

組是用戶的集合。組的主要目的是允許一個用戶與組內的其他成員共用文件訪問。

1.6 展望未來

到目前為止,你已經看到了什麼構成了運行中的Linux系統。用戶進程構成了你直接與之交互的環境;內核管理著進程和硬體。內核和進程都駐留在記憶體中。

這些都是很好的背景信息,但你不能僅僅通過閱讀來瞭解Linux系統的細節,你需要親身體驗。下一章將通過教授你一些用戶空間的基礎知識開始你的旅程。在這一過程中,你會瞭解到本章沒有討論的Linux系統的主要部分:長期存儲(磁碟、文件等)。畢竟,你需要把你的程式和數據儲存在某個地方。

釘釘或微信號: pythontesting 微信公眾號:pythontesting
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 面試題==知識點,這裡所記錄的面試題並不針對於面試者,而是將這些面試題作為技能知識點來看待。不以刷題進大廠為目的,而是以學習為目的。這裡的知識點會持續更新,目錄也會隨時進行調整。 ...
  • 簡訊在實現的邏輯上,也遵循消息中心的基礎設計,即消息生產之後,通過消息中心進行投遞和消費,屬於典型的生產消費模型; ...
  • # 1.新建python項目 1. 在編寫程式之前,我們需要新建一個項目(Project),在桌面雙擊PyCharm的快捷方式![image](https://img2023.cnblogs.com/blog/3179433/202305/3179433-20230526074257088-7431 ...
  • # WPF佈局基礎 ## WPF的佈局原則 + 一個視窗中只能包含一個元素 + 不應顯示設置元素尺寸 + 不應使用坐標設置元素的位置 + 可以嵌套佈局容器 ## WPF有哪些佈局容器? + Grid:網格。可以自定義行和列並通過行列的數量、行高和列寬來調整控制項的佈局。近似於HTML中的Table。 ...
  • 1. 什麼是MAF和MEF? MEF和MEF微軟官方介紹:https://learn.microsoft.com/zh-cn/dotnet/framework/mef/ MEF是輕量化的插件框架,MAF是複雜的插件框架。 因為MAF有進程隔離和程式域隔離可選。我需要插件進程隔離同時快速傳遞數據,最後 ...
  • 有個.NET面試官反饋面試了一個小白,問他用過哪些.NET庫,結果只回答上了幾個。作為一個.NET開發者,瞭解一些常用的.NET庫是非常重要的。本文將介紹.NET開發人員應該瞭解的10個常用.NET庫,這些庫可以幫助開發人員提高開發效率、簡化開發流程,開發出優秀的.NET應用程式。 **1、Auto ...
  • 《機器人SLAM導航核心技術與實戰》第1季:第5章_機器人主機 視頻講解 【第1季】5.第5章_機器人主機-視頻講解 【第1季】5.1.第5章_機器人主機_X86與ARM主機對比-視頻講解 【第1季】5.2.第5章_機器人主機_ARM主機樹莓派3B+-視頻講解 【第1季】5.3.第5章_機器人主機_ ...
  • # shell 常用命令3 ## 1 sed 用來自動編輯文件,可以用來實現替換配置文件的配置 ```shell 語法: sed [-hnV][-e][-f][文本文件] ``` > **參數說明**: > > - -e\或--expression=\ 以選項中指定的script來處理輸入的文本文件 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...