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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...