1. 程式人生 > >Linux系統呼叫的最終指南

Linux系統呼叫的最終指南

1.概述

這篇部落格解釋了Linux程式如何呼叫Linux核心中的函式。

它將概述幾種進行系統呼叫的不同方法,如何手工製作自己的程式集來進行系統呼叫(包括示例),系統呼叫的核心入口點,系統呼叫的核心出口點,glibc包裝器,bug等等。

2.什麼是系統呼叫

當您執行一個呼叫了open、fork、read、write(以及許多其他)的程式時,您正在進行系統呼叫。

系統呼叫是程式進入核心執行某些任務的方式。程式使用系統呼叫來執行各種操作,例如:建立程序、執行網路和檔案IO等等。

通過檢索syscalls(2)的手冊頁,可以找到系統呼叫的列表。

使用者程式有幾種不同的方式進行系統呼叫,而進行系統呼叫的低階指令在不同的CPU架構中有所不同。

作為一名應用程式開發人員,您通常不需要考慮如何準確地進行系統呼叫。您只需包含適當的標頭檔案,然後像呼叫普通函式一樣呼叫它。

glibc提供了包裝器程式碼,它將您從安排傳遞的引數並進入核心的底層程式碼中抽象出來。
在深入研究如何進行系統呼叫之前,我們需要定義一些術語,並檢查稍後將出現的一些核心思想。

2.先前準備

2.1 硬體和軟體

本文假設:

  • 您使用的是32位或64位Intel或AMD CPU。關於這些方法的討論可能對使用其他系統的人有用,但是下面的程式碼示例包含特定於cpu的程式碼。
  • 您對Linux核心3.13.0版本感興趣。其他核心版本將是類似的,但是具體的行號、程式碼組織和檔案路徑將有所不同。GitHub上有3.13.0核心原始碼樹。
  • 您對glibc或glibc派生的libc實現(例如,eglibc)感興趣。

在這篇博文中,x86-64將提到64位Intel和AMD CPU,它們都是基於x86架構的。

2.2 使用者程式、核心和CPU特權級別

使用者程式(如您的編輯器、終端、ssh守護程序等)需要與Linux核心互動,以便核心能夠代表您的使用者程式執行一組它們不能自己執行的操作。

例如,如果使用者程式需要執行某種IO(開啟、讀、寫等)或修改其地址空間(mmap、sbrk等),它必須觸發核心執行,以代表它完成這些操作。

是什麼阻止使用者程式自己執行這些操作?

事實證明,x86-64 cpu有一個稱為特權級別1

的概念。特權級別是一個複雜的主題,比較適合使用單獨的部落格來解釋它。就本文而言,我們可以(大大)簡化特權級別的概念,方法是:

  1. 特權級別是一種訪問控制手段。當前的特權級別決定可以執行哪些CPU指令和IO。
  2. 核心執行在最特權級別,稱為“Ring 0”。使用者程式在較低的級別上執行,通常是“Ring 3”。

為了讓使用者程式執行某些特權操作,它必須引起特權級別的更改(從“Ring 3”更改為“Ring 0”),以便核心可以執行。

有多種方法可以引起特權級別的更改,並觸發核心執行某些操作。

讓我們從一種導致核心執行的常見方法開始:中斷。

2.3 中斷

您可以將中斷看作是由硬體或軟體生成(或“引發”)的事件。

硬體裝置引發硬體中斷,通知核心發生了特定事件。這種型別的中斷的一個常見例子是當NIC【Network Interface Card】(即網絡卡、網路介面卡)接收到一個包時產生的中斷。

軟體中斷是通過執行一段程式碼引發的。在x86-64系統上,可以通過執行int指令引發軟體中斷。

中斷通常有分配給它們的數字。有些中斷的數字有特殊的含義。

您可以想象一個駐留在CPU記憶體中的陣列。這個陣列中的每個條目對映到一箇中斷號。每個條目包含一個函式的地址,當接收到這個中斷時,CPU將開始執行這個函式,同時還包含一些選項,比如中斷處理函式應該在哪個特權級別執行。
這是一張來自Intel CPU手冊的圖片,展示了這個陣列中的一個條目的佈局:
在這裡插入圖片描述


  1. x86指令集中的特權級別控制當前在處理器上執行的程式對資源(如記憶體區域、I/O埠和特殊指令)的訪問。有4個特權級別,從0到3。大多數現代作業系統對核心/執行程式使用0級,對應用程式使用3級。級別n可用的任何資源對級別0到n也是可用的,所以特權級別是環。當較弱的特權程序試圖訪問較高的特權程序時,作業系統會報告一般的保護錯誤異常。
    沒有必要使用所有四個特權級別。目前市場份額較大的作業系統,包括Microsoft Windows、macOS、Linux、iOS、Android等,大多采用單位元的分頁機制,指定許可權級別為管理員或使用者(U/S位元)。Windows NT使用兩級系統。在8086中的實際模式程式在第0級(最高特權級)執行,而在8086中的虛擬模式在第3級執行所有程式。
    x86 ISA家族支援的多個特權級別的潛在未來用途包括容器化和虛擬機器。主機作業系統核心可以使用具有完全特權訪問的指令(核心模式),而在虛擬機器或容器中的來賓作業系統上執行的應用程式可以在使用者模式中使用最低級別的特權。虛擬機器和客戶作業系統核心本身可以使用中級指令特權來呼叫和虛擬化核心模式操作,例如從客戶作業系統的角度進行系統呼叫 ↩︎