【操作系統-Day 5】通往內核的唯一橋梁:系統調用 (System Call)

Langchain系列文章目錄

01-玩轉LangChain:從模型調用到Prompt模板與輸出解析的完整指南
02-玩轉 LangChain Memory 模塊:四種記憶類型詳解及應用場景全覆蓋
03-全面掌握 LangChain:從核心鏈條構建到動態任務分配的實戰指南
04-玩轉 LangChain:從文檔加載到高效問答系統構建的全程實戰
05-玩轉 LangChain:深度評估問答系統的三種高效方法(示例生成、手動評估與LLM輔助評估)
06-從 0 到 1 掌握 LangChain Agents:自定義工具 + LLM 打造智能工作流!
07-【深度解析】從GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【萬字長文】MCP深度解析:打通AI與世界的“USB-C”,模型上下文協議原理、實踐與未來

Python系列文章目錄

PyTorch系列文章目錄

機器學習系列文章目錄

深度學習系列文章目錄

Java系列文章目錄

JavaScript系列文章目錄

Python系列文章目錄

Go語言系列文章目錄

Docker系列文章目錄

操作系統系列文章目錄

01-【操作系統-Day 1】萬物之基:我們為何離不開操作系統(OS)?
02-【操作系統-Day 2】一部計算機的進化史詩:操作系統的發展歷程全解析
03-【操作系統-Day 3】新手必看:操作系統的核心組件是什么?進程、內存、文件管理一文搞定
04-【操作系統-Day 4】揭秘CPU的兩種工作模式:為何要有內核態與用戶態之分?
05-【操作系統-Day 5】通往內核的唯一橋梁:系統調用 (System Call)


文章目錄

  • Langchain系列文章目錄
  • Python系列文章目錄
  • PyTorch系列文章目錄
  • 機器學習系列文章目錄
  • 深度學習系列文章目錄
  • Java系列文章目錄
  • JavaScript系列文章目錄
  • Python系列文章目錄
  • Go語言系列文章目錄
  • Docker系列文章目錄
  • 操作系統系列文章目錄
  • 摘要
  • 一、為何需要系統調用:應用程序的“權力”局限
    • 1.1 系統調用的核心作用
  • 二、系統調用(System Call)的本質
    • 2.1 什么是系統調用?
    • 2.2 系統調用與普通函數調用的區別
  • 三、系統調用的“穿越之旅”:從用戶態到內核態
    • 3.1 核心機制:陷入(Trap)
    • 3.2 詳細流程剖析
        • (1) 準備階段:傳遞參數
        • (2) 執行階段:陷入內核
        • (3) 硬件響應:切換狀態
        • (4) 內核處理:執行服務
        • (5) 返回階段:功成身退
        • (6) 回到用戶程序
    • 3.3 一個具體實例:以 Linux `write()` 為例
  • 四、包羅萬象:系統調用的分類
  • 五、總結


摘要

本文是“操作系統從入門到精通”系列的第五篇,我們將深入探討連接應用程序與操作系統內核的唯一橋梁——系統調用(System Call)。在上一篇文章中,我們理解了為何要有內核態與用戶態之分,本文將聚焦于應用程序如何跨越這道“權限鴻溝”,安全地請求操作系統提供服務。我們將從系統調用的概念與必要性出發,詳細拆解一次完整的系統調用過程,包括陷入(Trap)、用戶態到內核態的切換、內核服務執行及返回的全過程。最后,我們會對常見的系統調用進行分類,幫助讀者建立一個清晰、完整的知識圖譜。無論您是編程新手還是希望夯實基礎的進階者,本文都將為您揭開系統調用神秘的面紗。

一、為何需要系統調用:應用程序的“權力”局限

在上一章中,我們學習了 CPU 的兩種工作狀態:用戶態(User Mode)和內核態(Kernel Mode)。這種設計的核心目的是保護和安全。操作系統內核作為掌管所有硬件資源的“大管家”,運行在至高無上的內核態,可以執行任何指令。而我們日常編寫和運行的應用程序,則被限制在用戶態,它們的“權力”非常有限,無法執行某些高風險的“特權指令”,例如直接訪問硬件、修改頁表、開關中斷等。

那么,問題來了:如果一個應用程序(比如一個文本編輯器)想要讀取硬盤上的文件內容,或者一個網絡瀏覽器想要發送數據到網卡,這些操作都涉及到直接與硬件打交道,應用程序本身又沒有這個權限,該怎么辦?

這就好比一個普通市民(應用程序)想辦理一項需要政府部門(操作系統內核)審批的業務(訪問硬件資源)。市民不能直接闖入政府辦公室自己動手蓋章,而是需要遵循一套合法的流程,向指定的辦事窗口(系統調用接口)提交一份申請書(發起系統調用),由窗口的工作人員(內核中的服務例程)來完成后續的操作。

因此,系統調用正是操作系統提供的、允許用戶態程序向內核“提需求”的唯一、合法且受控的通道

1.1 系統調用的核心作用

  • 提供統一接口:操作系統將對底層硬件的復雜、多樣化操作封裝成一系列標準、統一的函數接口(即系統調用),應用程序開發者無需關心具體硬件型號和驅動細節,只需調用這些接口即可。
  • 保證系統安全:通過這道唯一的橋梁,內核可以對應用程序的每一個請求進行嚴格的審查。比如,檢查文件訪問權限、檢查內存地址是否越界等。只有合法、安全的請求才會被執行,從而有效防止了惡意或有缺陷的程序破壞整個系統。

二、系統調用(System Call)的本質

2.1 什么是系統調用?

系統調用 (System Call),從本質上講,是操作系統內核提供給應用程序的一組編程接口 (API)。當應用程序需要執行任何超越其權限范圍的操作時,它就會請求內核代為執行。這個“請求”動作,就是一次系統調用。

我們可以將系統調用理解為應用程序寫給內核的一封詳盡的**“委托書”**。這封委托書上清晰地寫明了:

  1. 希望內核做什么:例如,“我想讀取一個文件”,這就是請求的服務類型。
  2. 完成任務需要哪些信息:例如,要讀取哪個文件(文件名)、把內容讀到哪里(內存地址)、要讀多少(字節數)等,這些都是傳遞給內核的參數。

2.2 系統調用與普通函數調用的區別

初學者很容易將系統調用與我們編程時常用的普通函數調用(例如,自己定義的 add(a, b) 函數)混淆。雖然它們在 C 語言等高級語言中的調用形式看起來很相似(如 read(...) vs add(...)),但其底層實現和執行流程卻有天壤之別。

特性普通函數調用 (Function Call)系統調用 (System Call)
執行空間用戶空間內完成,不涉及狀態切換。跨越用戶空間內核空間,涉及狀態切換。
執行狀態調用前和調用后,CPU 都處于用戶態調用時,CPU 從用戶態切換到內核態,返回時再切回用戶態
執行開銷開銷小,僅涉及函數棧幀的創建和銷毀。開銷大,包含狀態切換、參數傳遞、內核驗證等多個步驟。
實現方由應用程序自身或其鏈接的庫提供。操作系統內核實現。
調用方式直接的指令跳轉到函數地址。通過特殊的**“陷入”指令 (Trap Instruction)** 來觸發。

三、系統調用的“穿越之旅”:從用戶態到內核態

系統調用的核心在于它如何實現從低權限的用戶態“穿越”到高權限的內核態。這個過程并非簡單的函數跳轉,而是一個由硬件和操作系統協同完成的、嚴謹而精妙的過程。

3.1 核心機制:陷入(Trap)

應用程序無法直接調用位于內核空間的函數。為了啟動系統調用,應用程序會執行一條特殊的CPU指令,這條指令被稱為陷入指令(Trap Instruction)或系統調用指令。在不同的CPU架構上,這條指令的名字可能不同,例如在 x86 架構中,早期使用 int 0x80(軟件中斷),現在則推薦使用更高效的 syscall 指令。

執行陷入指令會引發一個硬件事件,這個事件會主動地讓CPU暫停當前的用戶程序,并將控制權轉移給操作系統內核中預先設定好的一個特定處理程序,這個過程就叫做陷入 (Trap)

3.2 詳細流程剖析

一次完整的系統調用,就像一次精心策劃的“短途旅行”,往返于用戶態和內核態之間。下面我們以一個簡化的模型來剖析其詳細步驟:

(1) 準備階段:傳遞參數

應用程序在執行陷入指令之前,必須先準備好“委托書”的內容。

  1. 指定服務:將唯一的系統調用號(一個整數,代表要請求哪種服務,例如 1 代表 write2 代表 open)放入一個約定的寄存器中(如 rax 寄存器)。
  2. 提供參數:將調用該服務所需的其他參數(如文件描述符、內存緩沖區地址、要讀寫的字節數等)依次放入其他約定的寄存器中。如果參數過多,也可能通過棧來傳遞。
(2) 執行階段:陷入內核

用戶程序執行 syscall(或類似的)陷入指令。

(3) 硬件響應:切換狀態

CPU硬件檢測到這條指令后,會自動完成以下一系列動作:

  1. 切換到內核態:將 CPU 的狀態位從用戶態修改為內核態。
  2. 保存“案發現場”:將當前的用戶程序執行位置(程序計數器 PC)和其他關鍵寄存器的值保存到內核指定的內存區域(通常是內核棧)中。這至關重要,以便將來能準確返回。
  3. 跳轉到處理程序:根據陷入指令的類型,跳轉到內核中預設的**系統調用總入口(Trap Handler)**開始執行。
(4) 內核處理:執行服務

控制權現在完全交給了內核。

  1. 查找服務例程:系統調用處理程序首先從寄存器中取出系統調用號
  2. 參數驗證:它會像一個嚴格的門衛,檢查用戶程序傳遞過來的參數是否合法(例如,指針是否指向了用戶空間合法的內存地址)。
  3. 調用具體實現:如果驗證通過,內核會根據系統調用號在一個名為系統調用表 (System Call Table) 的數組中找到對應的內核函數(例如 sys_write, sys_open),并執行它。
  4. 執行真正的操作sys_write 等內核函數開始真正地與硬件交互,完成用戶請求的任務。
(5) 返回階段:功成身退
  1. 準備返回值:內核服務完成后,會將結果(例如成功寫入的字節數,或是一個錯誤碼)存放到一個約定的寄存器中(通常也是 rax)。
  2. 恢復“案發現場”:內核執行一條特殊的返回指令(如 sysexitiret),這條指令會讓硬件:
    • 恢復用戶寄存器:將之前保存的用戶程序狀態(PC、其他寄存器)從內核棧中恢復出來。
    • 切換回用戶態:將 CPU 狀態位從內核態改回用戶態。
(6) 回到用戶程序

控制權回到用戶程序,它從剛才執行 syscall 指令的下一條指令處繼續執行,并可以從指定的寄存器中獲取系統調用的返回結果。至此,一次完整的系統調用結束。

3.3 一個具體實例:以 Linux write() 為例

讓我們看看當你在 C 代碼中寫下一行 write(1, "hello\n", 6); 時,幕后發生了什么。

#include <unistd.h>int main() {// 向標準輸出(文件描述符為 1)寫入字符串 "hello\n"// 這個函數調用最終會觸發一次系統調用write(1, "hello\n", 6); return 0;
}

這段代碼的執行流程會大致遵循以下路徑(以 x86-64 Linux 為例):

  1. 用戶態:程序調用 C 庫 glibc 提供的 write 函數封裝。
  2. 用戶態glibcwrite 函數負責準備工作:
    • 將系統調用號 1 (代表 __NR_write) 放入 rax 寄存器。
    • 將第一個參數 1 (文件描述符) 放入 rdi 寄存器。
    • 將第二個參數 "hello\n" 的內存地址放入 rsi 寄存器。
    • 將第三個參數 6 (長度) 放入 rdx 寄存器。
  3. 用戶態glibc 執行 syscall 指令。
  4. 硬件:CPU 捕獲指令,保存用戶態上下文,切換到內核態,跳轉到內核的系統調用入口點。
  5. 內核態:內核的系統調用處理程序讀取 rax 的值為 1,知道用戶想執行 write
  6. 內核態:內核檢查 rdi, rsi, rdx 中的參數,確認文件描述符 1 是合法的,并且內存地址指向用戶空間。
  7. 內核態:內核調用內部的 sys_write 函數,該函數找到與文件描述符 1 關聯的設備驅動(通常是終端驅動),并將數據 “hello\n” 發送給它。
  8. 內核態sys_write 執行完畢,返回成功寫入的字節數 6。這個返回值被放入 rax 寄存器。
  9. 內核態:內核執行 sysexit 指令。
  10. 硬件:CPU 恢復用戶態上下文,切換回用戶態
  11. 用戶態glibcwrite 函數封裝從 rax 寄存器中取回返回值 6,并將其作為 C 函數的返回值。程序繼續執行。

四、包羅萬象:系統調用的分類

系統調用覆蓋了應用程序與操作系統交互的方方面面。為了便于管理和理解,通常將它們按功能分為以下幾大類:

分類說明常見系統調用舉例 (Linux)
進程控制 (Process Control)負責進程的創建、終止、等待、屬性設置等。是多任務操作系統的基石。fork(), clone(), execve(), exit(), wait4(), getpid()
文件操作 (File Manipulation)負責文件的創建、刪除、打開、關閉、讀寫和屬性設置。open(), close(), read(), write(), lseek(), stat()
設備管理 (Device Management)負責請求和釋放設備、讀寫設備數據等,通常通過文件操作接口實現。ioctl(), read(), write() (作用于設備文件時)
信息維護 (Information Maintenance)負責獲取或設置系統及進程的信息,如時間、系統數據、進程屬性等。time(), gettimeofday(), getrusage()
通信 (Communication)負責進程間的通信(IPC),是構建復雜協作應用的基礎。pipe(), socket(), shmget() (共享內存), msgget() (消息隊列)
內存管理 (Memory Management)負責內存的分配和映射。brk(), mmap()

五、總結

本文深入探討了操作系統中承上啟下的關鍵概念——系統調用。通過這篇文章,我們應該理解以下核心要點:

  1. 存在的意義:系統調用是操作系統為用戶程序提供的、用于請求內核服務的唯一、安全、標準的接口,它是隔離用戶態和內核態、保護系統安全的基石。
  2. 核心過程:一次系統調用的生命周期始于用戶態的陷入(Trap)指令,經歷由硬件輔助的上下文切換進入內核態,由內核執行具體服務,最后再切換回用戶態并返回結果。
  3. 成本考量:與普通函數調用相比,系統調用因為涉及兩次上下文切換(用戶態 -> 內核態 -> 用戶態),其執行開銷要大得多。因此,在性能敏感的應用中,應避免頻繁且不必要的系統調用。
  4. 功能范疇:系統調用涵蓋了進程控制、文件操作、設備管理、進程間通信等所有需要內核介入的功能,構成了現代應用程序能夠運行的底層支持框架。

理解了系統調用,就等于掌握了應用程序與操作系統對話的語言。在后續的章節中,無論是討論進程管理、內存管理還是文件系統,我們都會發現,它們所有功能的最終實現,都離不開一次次的系統調用。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914274.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914274.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914274.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

完整 Spring Boot + Vue 登錄系統

項目名稱&#xff1a;springboot-vue-login-template? 功能一覽模塊功能后端Spring Boot MyBatis Plus JWT Shiro數據庫MySQL 用戶表前端Vue3 Element Plus Axios登錄流程用戶名/密碼驗證 → 返回 Token → 存儲 LocalStorage權限控制攔截器校驗 Token Shiro 角色權限跨…

Redis 基礎詳細介紹(Redis簡單介紹,命令行客戶端,Redis 命令,Java客戶端)

1. Redis 簡介Redis&#xff08;Remote Dictionary Server&#xff09;是一個開源的內存數據庫&#xff0c;遵守 BSD 協議&#xff0c;它提供了一個高性能的鍵值&#xff08;key-value&#xff09;存儲系統&#xff0c;常用于緩存、消息隊列、會話存儲等應用場景。1.1 特征豐富…

C/C++數據結構之多維數組

概述多維數組&#xff0c;實際上就是“數組的數組”。最常見的是二維數組&#xff0c;就像一個表格&#xff0c;擁有行和列。而三維數組則可以想象為多個這樣的表格堆疊起來形成的一個立方體。依此類推&#xff0c;我們可以構建四維、五維甚至更高維度的數組。多維數組主要用于…

[Rust 基礎課程]選一個合適的 Rust 編輯器

市面上現在有很多編輯器都可以開發 Rust&#xff0c;很多都是以安裝 Rust 插件的形式來對 Rust 做支持&#xff0c;本課程使用 RustRover&#xff0c;如果你喜歡其他的編輯器&#xff0c;可以自己搗鼓下。 RustRover https://www.jetbrains.com/rust/ jetbrains 專門對于 Ru…

【零基礎學AI】第37講:提示詞工程(Prompt Engineering)

本節課你將學到 理解提示詞工程的核心原理 掌握5種實用的Prompt設計模式 學會優化提示詞的評估方法 實現一個智能問答系統優化案例 開始之前 環境要求 Python 3.8安裝包&#xff1a;pip install openai tiktokenOpenAI API密鑰&#xff08;免費注冊&#xff1a;https://plat…

莫蘭迪色系工作總結匯報PPT模版分享

莫蘭迪色工作總結PPT模版&#xff0c;莫蘭迪調色板PPT模版&#xff0c;莫蘭迪色系高級簡約PPT模版&#xff0c;莫蘭迪色系工作匯報&#xff0c;莫蘭迪總結匯報模版 莫蘭迪色系工作總結匯報PPT模版分享&#xff1a;https://pan.quark.cn/s/35bcaa03c837

uniapp的app項目,某個頁面長時間無操作,返回首頁

最開始想做成一個公共的&#xff0c;完全提取出來的一個組件&#xff0c;組件設置背景透明&#xff0c;到時候哪個頁面需要&#xff0c;直接引入組件就可以了&#xff0c;所以最開始做的是一個vue的組件&#xff0c;在組件中&#xff0c;監聽頁面的touchstart&#xff0c;但是這…

【實證分析】上市公司綠色戰略數據集(2000-2023年)

數據簡介&#xff1a;綠色戰略是指企業根據其所處的外部環境&#xff08;包括“綠色浪潮”等環保趨勢&#xff09;和企業自身的經營條件&#xff0c;為實現企業生存與發展質量的持續提升&#xff0c;而對企業生產經營活動進行綠色化改造的總體規劃。這包括制定企業綠色可持續發…

【SpringAI】7. 基于 milvus 的向量檢索

SpringAI 基于 milvus 的向量檢索 向量數據庫可以使用 milvus&#xff0c;redis,Elasticsearch 等&#xff0c;本文以 milvus 為例&#xff1a; 1. 啟動milvus 為了盡可能快速上手springai的vectordb功能&#xff0c;我們推薦使用云上的milvus&#xff0c;注冊就能創建免費的…

如何使用數字化動態水印對教育視頻進行加密?

文章目錄前言一、什么是數字化動態水印二、使用數字化動態水印對教育視頻加密的好處&#xff1f;三、數字化動態水印的實現原理四、如何實現數字化動態水印對教育視頻加密總結前言 教育資源數字化蓬勃發展的今天&#xff0c;優質視頻課程已成為機構的核心知識資產。然而&#…

解決bash終端的路徑名稱亂碼問題

解決bash終端的路徑名稱亂碼 默認打開了zsh&#xff0c;當我輸入bash后&#xff0c;就出現了亂碼 (context_rag) [23fanyaohead1]~/mycode-thesis% bash (context_rag) [%n%m]%~%#亂碼原因排查 我遇到了終端亂碼問題&#xff0c;需要檢查當前的終端環境和編碼設置&#xff0c;下…

【深度學習】【入門】Sequential的使用和簡單神經網絡搭建

1.Sequential的概念它是一種按順序封裝神經網絡層的容器&#xff0c;能讓層按照添加順序依次執行計算&#xff0c;簡化網絡搭建流程2.Sequential的作用1.代碼簡潔化對比不用 Sequential 時手動搭建層的繁瑣代碼&#xff08;如每層需手動定義并連接&#xff09;&#xff0c;展示…

前端開發中的資源緩存詳解

資源緩存用于緩存靜態資源,良好的緩存策略可以減少資源重復加載進而提高網頁的整體加載速度。 通常瀏覽器緩存策略分為兩種:強緩存和協商緩存,當然還包括 service worker。 瀏覽器在資源加載時,根據請求頭中的 expires 和 cache-control 值來判斷是否命中強緩存,命中則直…

零基礎入門指南:華為數通認證體系詳解

一、華為數通認證的定位與行業價值華為數通認證&#xff08;Datacom&#xff09;是ICT領域核心方向&#xff0c;覆蓋路由器、交換機等網絡基礎設備技術&#xff0c;被譽為“網絡行業的骨骼”。2020年升級為Datacom認證體系&#xff0c;新增SDN、VXLAN、網絡自動化等前沿技術&am…

超低功耗CC2340R SimpleLink? 系列 2.4GHz 無線 MCU支持BLE5.3/Zigbee/Thread/專有協議

CC2340R SimpleLink? 系列 2.4GHz 無線 MCU支持BLE5.3/Zigbee/Thread/專有協議優勢簡介性能介紹應用場景優勢簡介 CC2340R SimpleLink? 系列器件為 2.4GHz 無線微控制器 (MCU)&#xff0c;面向低功耗 Bluetooth5.3、Zigbee、Thread 和專有 2.4GHz 應用。這些器件針對低功耗無…

若依前后端分離Vue3版本接入阿里云OSS

一、引入依賴首先在commom 模塊的pom 下面引入 阿里云OSS 的 依賴<!-- 阿里云oss --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version></depende…

2025年微軟mos備考攻略-窮鬼版

說實話&#xff0c;微軟MOS認證是微軟官芳推出的辦公軟件方面的認證&#xff0c;考試難度真的不大&#xff0c;完全沒必要報班&#xff0c;自學完全OK&#xff01;一、25 年報考MOS認證詳情報名時間&#xff1a;隨時可以在官網或ji構報名&#xff08;ji構報名會送備考資料&…

數據庫版本自動管理

FlywayDB 是一款 開源數據庫版本管理工具&#xff0c;開發中將表結構的變更或數據初始化腳本維護好&#xff0c;更新到測試環境或線上發版啟動服務的時候&#xff0c;會檢測版本號自動執行數據庫變更&#xff0c;可以減少每次發版到其他環境的人工執行操作。 工作流程初始化階段…

解決Linux綁定失敗地址已使用(端口被占用)的問題

文章目錄解決 bind failed: Address already in use 問題一、問題原因1. **端口已經被其他程序占用**2. **端口處于 TIME_WAIT 狀態**3. **未正確關閉套接字**二、如何排查和解決問題1. **確認端口是否被占用**2. **查找并殺掉占用端口的進程**3. **等待端口釋放&#xff08;TI…

Ragas的Prompt Object

Prompt在Ragas中被用在各種指標、合成數據生成任務中。同時也為提供了替換各種自動以提示詞的方式。Ragas提供了如下幾種Prompt Objects。 instruction:prompt的基礎組成,通過自然語言清晰的描述LLM需要完成的任務。在prompt object中用instruction變量定義。few-shot exampl…