Linux筆記---內核態與用戶態

用戶態(User Mode)

  • 權限級別:較低,限制應用程序直接訪問硬件或關鍵系統資源。

  • 適用場景:普通應用程序的運行環境。

  • 限制:無法執行特權指令(如操作I/O端口、修改內存管理單元配置等)。

內核態(Kernel Mode)

  • 權限級別:最高,允許完全訪問硬件和系統資源。

  • 適用場景:操作系統內核代碼的執行環境。

  • 能力:可執行所有CPU指令,管理進程、內存、設備驅動等核心功能。


1. 操作系統的運行方式

文章開頭給出的概念是站在用戶的角度上來講的,對于加深我們對二者的理解來說,無異于杯水車薪。要搞清楚用戶態與內核態的概念與意義,我們首先要了解操作系統是如何運行的。

如下是Linux0.11版本中,任務0(init)的主函數部分代碼:

void main_rename(void)		
{...... // 這里省略前面的初始化代碼
/** 注意!! 對于任何其它的任務,'pause()'將意味著我們必須等待收到一個信號才會返* 回就緒運行態,但任務0(task0)是唯一的意外情況(參見'schedule()'),因為任* 務0 在任何空閑時間里都會被激活(當沒有其它任務在運行時),* 因此對于任務0'pause()'僅意味著我們返回來查看是否有其它任務可以運行,如果沒* 有的話我們就回到這里,一直循環執行'pause()'。*/for(;;) pause();
}

任務0是內核啟動后創建的第一個用戶態任務(注意任務0不等同于操作系統本身),它的主要作用是在系統空閑時讓出CPU,執行for(;;) pause();循環,通過調用pause()系統調用觸發schedule(),主動讓出CPU給其他任務。

pause() 的作用

  • 常規行為:對于普通任務(非任務 0),pause() 會使任務進入可中斷睡眠狀態,直到收到信號后被喚醒。

  • 任務 0 的特殊性
    任務 0 是內核初始化后創建的第一個任務(空閑任務),它的 pause() 行為被刻意修改為:

    • 不進入睡眠:直接調用 schedule() 主動觸發調度。

    • 輪詢機制:若沒有其他任務可運行,調度器會再次選中任務 0,繼續執行循環。

簡單來說,這個死循環的作用就是:不斷觸發主動調度,并作為沒有其他進程正在運行時的默認動作。?

注意:操作系統內核并不是以一個進程的形式存在的,也就是說內核不是依靠進程調度來獲得CPU的(畢竟調度本身就是操作系統的任務)。內核是操作系統的核心部分,它是一段運行在特權級別的代碼,直接與硬件交互,對系統進行全面的控制和管理。

那么,操作系統的內核在何時能得到運行呢?

在任務0作為一個進程存在的同時,操作系統的內核在不斷地等待著別人請求自己的服務,而請求操作系統服務的方式就是引發中斷,喚醒處于等待狀態之中的操作系統。?

可以說,除了初始化以外,在沒有中斷的時候,操作系統的代碼是不執行的;又或者說操作系統就是初始化程序 + 中斷處理程序。

包括schedule()主動觸發調度,本質上也是依靠觸發軟中斷來請求操作系統的進程調度服務的。

接下來,我們再來介紹一下中斷到底是什么,以及在操作系統中有哪幾類中斷。


2. 中斷

中斷(Interrupt) 是計算機系統中一種核心的事件驅動機制,允許CPU暫停當前執行的任務,轉而處理優先級更高或需要即時響應的外部或內部事件。其本質是通過硬件或軟件觸發的信號,強制CPU切換執行流程,以保障系統的實時性、資源利用率和錯誤處理能力。


中斷的核心特性

  1. 異步性:中斷的發生與CPU當前執行的指令無關,隨時可能被觸發(如鍵盤輸入、定時器到期)。
  2. 優先級分層:不同中斷源(如硬件故障、磁盤I/O完成)有不同的優先級,高優先級中斷可搶占低優先級中斷。
  3. 上下文保存:CPU在響應中斷前,會自動保存當前任務的狀態(如寄存器值、程序計數器PC),以便處理完成后恢復原任務。

中斷的分類

1. 硬件中斷(Hardware Interrupt)

  • 定義:由外部硬件設備通過中斷請求線(IRQ)主動觸發。

  • 特點

    • 異步性:與CPU當前執行的指令無關。

    • 可屏蔽性:可通過中斷屏蔽位(如x86的IF標志位)控制是否響應。

  • 子類型

    • 可屏蔽中斷(Maskable Interrupt)
      例如:鍵盤輸入、磁盤I/O完成、定時器中斷等。
      通過中斷控制器(如APIC或8259A)管理優先級。

    • 不可屏蔽中斷(Non-Maskable Interrupt, NMI)
      例如:硬件故障(內存校驗錯誤)、系統看門狗超時。
      CPU必須立即處理,無法通過軟件屏蔽。

2. ???????軟件中斷(Software Interrupt)

  • 定義:由程序執行特定指令(如intsyscall)主動觸發。

  • 特點

    • 同步性:由程序顯式調用,與指令流同步。

    • 不可屏蔽性:無法通過硬件屏蔽。

  • 子類型

    • 系統調用(System Call)
      用戶程序通過int 0x80(x86)或syscall(x86_64)切換到內核態。

    • 調試中斷(Breakpoint)
      例如:int 3指令觸發調試器斷點。

    • 異常(Exception)
      CPU執行指令時檢測到錯誤(如除零、頁錯誤),自動觸發。

2.1 硬件中斷

通過外部硬件中斷,操作系統就不需要對外設進行任何周期性的檢測或者輪詢。

由外部設備觸發的,中斷系統運行流程,叫做硬件中斷。

其中,中斷向量表在內存中的位置與格式由 CPU 架構硬性規定,中斷號實際上就是相對于中斷向量表起始地址的偏移量。當CPU獲得中斷號之后,就可以在中斷向量表當中查詢到對應的中斷服務程序的起始地址,進而轉向執行中斷服務程序。

而中斷服務程序則是由操作系統負責注冊到中斷向量表當中的:

// 下面是異常(陷阱)中斷程序初始化子程序。設置它們的中斷調用門(中斷向量)。
// set_trap_gate()與set_system_gate()的主要區別在于前者設置的特權級為0,后者是3。因此
// 斷點陷阱中斷int3、溢出中斷overflow 和邊界出錯中斷bounds 可以由任何程序產生。
// 這兩個函數均是嵌入式匯編宏程序(include/asm/system.h,第36 行、39 行)。
void trap_init(void)
{int i;set_trap_gate(0,&divide_error);// 設置除操作出錯的中斷向量值。以下雷同。set_trap_gate(1,&debug);set_trap_gate(2,&nmi);set_system_gate(3,&int3);	/* int3-5 can be called from all */set_system_gate(4,&overflow);set_system_gate(5,&bounds);set_trap_gate(6,&invalid_op);set_trap_gate(7,&device_not_available);set_trap_gate(8,&double_fault);set_trap_gate(9,&coprocessor_segment_overrun);set_trap_gate(10,&invalid_TSS);set_trap_gate(11,&segment_not_present);set_trap_gate(12,&stack_segment);set_trap_gate(13,&general_protection);set_trap_gate(14,&page_fault);set_trap_gate(15,&reserved);set_trap_gate(16,&coprocessor_error);
// 下面將int17-48 的陷阱門先均設置為reserved,以后每個硬件初始化時會重新設置自己的陷阱門。for (i=17;i<48;i++)set_trap_gate(i,&reserved);set_trap_gate(45,&irq13);// 設置協處理器的陷阱門。outb_p(inb_p(0x21)&0xfb,0x21);// 允許主8259A 芯片的IRQ2 中斷請求。outb(inb_p(0xA1)&0xdf,0xA1);// 允許從8259A 芯片的IRQ13 中斷請求。set_trap_gate(39,&parallel_interrupt);// 設置并行口的陷阱門。
}初始化串行中斷程序和串行接口。
void
rs_init (void)
{set_intr_gate (0x24, rs1_interrupt);	// 設置串行口1 的中斷門向量(硬件IRQ4 信號)。set_intr_gate (0x23, rs2_interrupt);	// 設置串行口2 的中斷門向量(硬件IRQ3 信號)。init (tty_table[1].read_q.data);	// 初始化串行口1(.data 是端口號)。init (tty_table[2].read_q.data);	// 初始化串行口2。outb (inb_p (0x21) & 0xE7, 0x21);	// 允許主8259A 芯片的IRQ3,IRQ4 中斷信號請求。
}

2.2?時鐘中斷

我們曾經使用過sleep,alarm等函數,也了解了時間片的概念,那么操作系統是如何計時的呢?

實際上,操作系統運行的一大依據就是時鐘中斷,顧名思義,這種中斷就是用來幫助系統計時的。

時鐘中斷本質上也是一種硬件中斷,這種中斷依靠一種特定的硬件設備來觸發:時鐘源。

早期的時候時鐘源就是上圖中的外設之一,但是鑒于其重要程度以及時鐘中斷的時效性,現在大多數的CPU都已經集成了中斷源,使中斷源能直接向CPU發送信號。

時鐘源發送時鐘中斷的時間間隔是固定的,由其頻率。時鐘源的頻率也叫CPU或者系統的主頻

時鐘中斷的核心作用
  1. 系統計時
    通過全局變量jiffies記錄自系統啟動以來的節拍數(每個節拍對應一次時鐘中斷),結合HZ(每秒節拍數,默認100~1000)實現時間計算。例如,jiffies/HZ可轉換為系統運行時間(秒)。

  2. 進程調度
    每次時鐘中斷會調用do_timer()函數更新進程時間片,觸發搶占式調度。進程的時間片本質上就是一個計數器,每次時鐘中斷都會使其減1,直到為0。

  3. 動態定時器管理
    內核通過紅黑樹或時間輪管理動態定時器(timer_list結構),時鐘中斷觸發時檢查并執行到期定時器的回調函數。

  4. 資源統計
    統計進程消耗的用戶態和內核態時間,更新系統負載平均值。

?2.3 軟中斷

系統調用本質上就是請求操作系統的服務,這就要求我們能從軟件層面上觸發中斷,即軟中斷。

為了讓操作系統支持進行系統調用,CPU也設計了對應的匯編指令(int 或者 syscall),可以讓CPU內部觸發中斷邏輯。

本質上,我們使用的系統調用函數內部的邏輯就是使用int 0x80指令請求操作系統提供指定的服務,其本身并不具備任務對系統進行操作的能力。

 打開文件函數。
// 打開并有可能創建一個文件。
// 參數:filename - 文件名;flag - 文件打開標志;...
// 返回:文件描述符,若出錯則置出錯碼,并返回-1。
int open(const char * filename, int flag, ...)
{register int res;va_list arg;// 利用va_start()宏函數,取得flag 后面參數的指針,然后調用系統中斷int 0x80,功能open 進行
// 文件打開操作。
// %0 - eax(返回的描述符或出錯碼);%1 - eax(系統中斷調用功能號__NR_open);
// %2 - ebx(文件名filename);%3 - ecx(打開文件標志flag);%4 - edx(后隨參數文件屬性mode)。va_start(arg,flag);res = va_arg(arg,int);_asm{mov eax,__NR_openmov ebx,filenamemov ecx,flagmov edx,resint 0x80mov res,eax}
/*	__asm__("int $0x80":"=a" (res):"0" (__NR_open),"b" (filename),"c" (flag),"d" (va_arg(arg,int)));*/
// 系統中斷調用返回值大于或等于0,表示是一個文件描述符,則直接返回之。if (res>=0)return res;
// 否則說明返回值小于0,則代表一個出錯碼。設置該出錯碼并返回-1。errno = -res;return -1;
}

可以看到open函數內部是使用嵌入式匯編的方式傳遞參數,并使用int 0x80觸發軟中斷。

軟中斷處理程序 _system_call 根據第一個參數 __NR_open 就能索引到需要調用的函數:

正真有能力對系統進行操作的,操作系統內部的系統調用函數被注冊到了一張表當中,這張表就是上面匯編程序索引到所需函數的依據:

?3. 內核態與用戶態的本質

經歷了上面的學習,相信大家對于內核態與用戶態的本質已經有了一定的想法。

即,執行用戶代碼時,系統就處于用戶態;因中斷而轉向執行中斷處理程序時(操作系統內核代碼),系統就處于內核態。

內核態的代碼是全局的,不受約束的(或者說只受到硬件約束);而用戶態的代碼是以進程的形式,在虛擬地址空間上運行的,受到操作系統的約束。

問題是,CPU在運行代碼時,如何區分其是內核代碼(特權級)還是用戶代碼(受限制)呢?

Linux內核態與用戶態的本質區別在于CPU特權級隔離內存訪問權限控制,這種設計通過硬件機制與軟件協同實現系統資源的保護:

  1. 特權級劃分
    x86架構通過Ring等級劃分權限(0-3級),Linux僅使用Ring0(內核態)和Ring3(用戶態)。關鍵寄存器CS(代碼段寄存器)的低2位存儲當前特權級(CPL):

    // 內核代碼段選擇子(CPL=0)
    #define __KERNEL_CS 0x10
    // 用戶代碼段選擇子(CPL=3)
    #define __USER_CS 0x1B
    
  2. 內存隔離機制

    • 頁表隔離:用戶態進程只能訪問用戶空間頁表項(VM_READ/VM_WRITE),內核態通過全局頁表swapper_pg_dir直接映射物理內存。

    • 地址空間劃分:x86_64下用戶空間為0x0000_0000_0000_0000 - 0x0000_7FFF_FFFF_FFFF,內核空間為0xFFFF_8000_0000_0000以上。也就是說,用戶代碼中地址的范圍與內核代碼中地址的范圍是互斥的,用戶態下無法使用內核地址,在內核態下無法使用用戶地址。

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

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

相關文章

Spring 代理與 Redis 分布式鎖沖突:一次鎖釋放異常的分析與解決

Spring 代理與 Redis 分布式鎖沖突&#xff1a;一次鎖釋放異常的分析與解決 Spring 代理與 Redis 分布式鎖沖突&#xff1a;一次鎖釋放異常的分析與解決1. 問題現象與初步分析2 . 原因探究&#xff1a;代理機制對分布式鎖生命周期的干擾3. 問題復現偽代碼4. 解決方案&#xff1…

SQL:多列匹配(Multiple-column Matching)

目錄 基礎概念 應用場景詳解 1. 多列等值匹配 2. 多列 IN 匹配&#xff08;集合匹配&#xff09; 3. 多列 JOIN 匹配&#xff08;復合鍵連接&#xff09; 4. 多列匹配 子查詢 5. 多列匹配 EXISTS 6. 多列匹配 UNION&#xff08;組合數據源&#xff09; 7. 多列匹配…

基于DeepSeek的智能客服系統實踐與創新

引言:AI大模型重塑客戶服務新范式 近年來,AI大模型技術的突破性進展正在深刻改變傳統客戶服務模式。作為國內領先的AI企業,DeepSeek憑借其創新的算法架構(如MoE混合專家模型、動態學習率調度器)和極致的成本效益(僅為同類模型成本的1/20),在自然語言理解、情感分析、多…

SGLang和vllm比有什么優勢?

環境&#xff1a; SGLang vllm 問題描述&#xff1a; SGLang和vllm比有什么優勢&#xff1f; 解決方案&#xff1a; SGLang和vLLM都是在大語言模型&#xff08;LLM&#xff09;推理和部署領域的開源項目或框架&#xff0c;它們各自有不同的設計目標和優勢。下面我綜合目前…

三、Hive DDL數據庫操作

在 Apache Hive 中&#xff0c;數據庫 (Database)&#xff0c;有時也被稱為模式 (Schema)&#xff0c;是組織和管理 表及其他對象的基本命名空間單元。熟練掌握數據庫層面的數據定義語言 (DDL) 操作&#xff0c;是構建清晰、有序的 Hive 數據倉庫的第一步。本篇筆記將詳細梳理 …

Redis(2):Redis + Lua為什么可以實現原子性

Redis 作為一款高性能的鍵值對存儲數據庫&#xff0c;與 Lua 腳本相結合&#xff0c;為實現原子性操作提供了強大的解決方案&#xff0c;本文將深入探討 Redis Lua 實現原子性的相關知識 原子性概念的厘清 在探討 Redis Lua 的原子性之前&#xff0c;我們需要明確原子性的概念…

科普:極簡的AI亂戰江湖

本文無圖。 大模型 ?2022年2月&#xff0c;?文生圖應用的鼻祖Midjourney上線。 ?2022年8月&#xff0c;?開源版的Midjourney&#xff0c;也就是Stable Diffusion上線。 2022年11月30日?&#xff0c;OpenAI正式發布ChatGPT-3.5。 此后&#xff0c;不斷有【大模型】面世&…

CSS- 4.5 css + div 布局 簡易網易云音樂 官網布置實例

本系列可作為前端學習系列的筆記&#xff0c;代碼的運行環境是在HBuilder中&#xff0c;小編會將代碼復制下來&#xff0c;大家復制下來就可以練習了&#xff0c;方便大家學習。 HTML系列文章 已經收錄在前端專欄&#xff0c;有需要的寶寶們可以點擊前端專欄查看&#xff01; 點…

【滑動窗口】LeetCode 1004題解 | 最大連續1的個數 Ⅲ

最大連續1的個數 Ⅲ 一、題目鏈接二、題目三、題目解析四、算法原理解法一&#xff1a;暴力枚舉 zero計數器解法二&#xff1a;滑動窗口 五、編寫代碼六、時空復雜度 一、題目鏈接 最大連續1的個數 Ⅲ 二、題目 三、題目解析 注意題目中說的是最多k次&#xff0c;在一個數組…

PyTorch音頻處理技術及應用研究:從特征提取到相似度分析

文章目錄 音頻處理技術及應用音頻處理技術音視頻摘要技術音頻識別及應用 梅爾頻率倒譜系數音頻特征爾頻率倒譜系數簡介及參數提取過程音頻處理快速傅里葉變換(FFT)能量譜處理離散余弦轉換 練習案例&#xff1a;音頻建模加載音頻數據源波形變換的類型繪制波形頻譜圖波形Mu-Law 編…

鴻蒙OSUniApp 實現的語音輸入與語音識別功能#三方框架 #Uniapp

UniApp 實現的語音輸入與語音識別功能 最近在開發跨平臺應用時&#xff0c;客戶要求添加語音輸入功能以提升用戶體驗。經過一番調研和實踐&#xff0c;我成功在UniApp項目中實現了語音輸入與識別功能&#xff0c;現將過程和方法分享出來&#xff0c;希望對有類似需求的開發者有…

2025年衛星遙感行業最新發展趨勢深度分析

一、國內發展趨勢&#xff1a;政策引領與技術突破雙輪驅動 &#xff08;一&#xff09;政策體系持續完善&#xff0c;頂層設計深化行業發展 國家級戰略與標準體系構建 中國政府將衛星遙感產業納入“十四五”規劃核心戰略&#xff0c;明確構建“通導遙”一體化空間基礎設施。20…

SIP協議棧--osip源碼梳理

文章目錄 osiposip主體結構體code main函數 狀態機轉化結構體code狀態轉換 sip事務結構體code osip_dialog結構體code 創建并發送200 OK響應 osip_message結構體code osip_eventcode 打印接收到的SIP消息 osip OSIP&#xff08;Open Source Implementation of SIP&#xff09;…

Linux之Yum源與Nginx服務篇

1.Yum源知識理論總結概括 Yum源概述 Yum 源 即軟件倉庫的標識&#xff0c;里面承載著軟件包集合 Yum源組成 包含模塊 【OS】、【everything】、【EPOL】、【debuginfo】、【source】、【update-source】 【os】:簡稱operator system 它內部包含操作系統的核心組件&#x…

從單體架構到微服務:架構演進之路

引言&#xff1a;當“大貨車”遇上“集裝箱運輸” 在軟件開發領域&#xff0c;單體架構曾像一輛載滿貨物的大貨車&#xff0c;將所有功能打包在一個應用中。但隨著業務復雜度飆升&#xff0c;這輛“大貨車”逐漸陷入泥潭&#xff1a;啟動慢如蝸牛、故障波及全局、升級如履薄冰……

AM32電調學習解讀九:ESC上電啟動關閉全流程波形分析

這是第九篇&#xff0c;前面的文章把各個模塊的實現都介紹了一輪&#xff0c;本章是從運行的角度結合波形圖&#xff0c;把整個流程走一遍。 先看下一運行的配置&#xff0c;我把一些配置關閉了&#xff0c;這樣跑起來會好分析一些&#xff0c;不同配置跑起來效果會有差異。使用…

全球寵物經濟新周期下的亞馬遜跨境采購策略革新——寵物用品賽道成本優化三維路徑

在全球"孤獨經濟"與"銀發經濟"雙輪驅動下&#xff0c;寵物用品市場正經歷結構性增長。Euromonitor數據顯示&#xff0c;2023年全球市場規模突破1520億美元&#xff0c;其中中國供應鏈貢獻度達38%&#xff0c;跨境電商出口增速連續三年超25%。在亞馬遜流量紅…

reshape/view/permute的原理

在pytorch中&#xff0c;Tensor的存儲是行主序的&#xff0c;也就是意味著最后一個維度的元素的存儲時連續的&#xff0c;reshape和view并不改變元素存儲的內存&#xff0c;僅僅改變訪問的間隔&#xff0c;下面舉例說明&#xff1b; 比如一個23的Tensor在內存中的存儲是連續的&…

upload-labs靶場通關詳解:第11關

一、分析源代碼 $is_upload false; $msg null; if (isset($_POST[submit])) {if (file_exists(UPLOAD_PATH)) {$deny_ext array("php","php5","php4","php3","php2","html","htm","phtml"…

L1-7 最短字母串【保姆級詳細講解】

請你設計一個程序&#xff0c;該程序接受起始字母和目標字母作為輸入&#xff0c;通過在字母表中向前或向后移動來計算兩個給定字母之間的最短路徑。然后&#xff0c;程序會沿著最短路徑打印出從起始字母到目標字母的所有字母。例如&#xff0c;如果輸入“c”和“k”作為起始字…