Linux 0.11源碼閱讀筆記-中斷過程

来源:https://www.cnblogs.com/cwcheng/archive/2022/03/29/16071685.html
-Advertisement-
Play Games

Linux 0.11源碼閱讀筆記-中斷過程 是什麼中斷 中斷發生時,電腦會停止當前運行的程式,轉而執行中斷處理程式,然後再返回原被中斷的程式繼續運行。中斷包括硬體中斷和軟體中斷,硬中斷是由外設自動產生的,軟中斷是程式通過int指令主動調用。中斷產生時,會有一個中斷號,根據中斷號可在中斷向量表中選擇 ...


Linux 0.11源碼閱讀筆記-中斷過程

是什麼中斷

中斷發生時,電腦會停止當前運行的程式,轉而執行中斷處理程式,然後再返回原被中斷的程式繼續運行。中斷包括硬體中斷和軟體中斷,硬中斷是由外設自動產生的,軟中斷是程式通過int指令主動調用。中斷產生時,會有一個中斷號,根據中斷號可在中斷向量表中選擇對應的中斷處理程式執行。

中斷在linux當中非常重要,是用戶態代碼與和心態代碼相互切換運行的橋梁。進程調度依賴於時鐘中斷進入內核,系統調用也是依賴int 80軟中斷進入內核執行。

中斷處理過程

以int 80中斷為例。system_call過程代碼是 int 80中斷處理程式,是所有系統調用的入口。位於linux-0.11/kernel/system_call.s文件中。

sytem_call執行過程

  1. 保存運行環境:保存被中斷程式的運行環境,包括指令地址(PC)、段等寄存器的值。
  2. 執行系統調用:根據系統調用號,查找系統調用函數地址表,並執行系統調用函數
  3. 執行調度程式:判斷進程時間片是否處於不可運行狀態(時間片用完或者處於阻塞狀態),若不可運行,則執行調度程式。
  4. 進行信號處理:若被中斷程式為用戶態進程,會先判斷信號是否產生,並執行相應的信號處理程式。
  5. 恢復運行環境:恢復被中斷程式的運行環境。

system_call代碼及註釋

### int 0x80 - linux系統調用入口點(調用中斷int 0x80,eax 中是調用號)
system_call:
	cmpl $nr_system_calls-1,%eax    # 調用號如果超出範圍的話就在eax中置-1並退出
	ja bad_sys_call
	
# 保存原段寄存器值
	push %ds                        
	push %es
	push %fs

# edx、ecx、ebx作為系統調用的參數
	pushl %edx
	pushl %ecx		# push %ebx,%ecx,%edx as parameters
	pushl %ebx		# to the system call
	
# 設置內核段
	movl $0x10,%edx	# set up ds,es to kernel space
	mov %dx,%ds
	mov %dx,%es
# fs指向用戶程式的數據段。
	movl $0x17,%edx		# fs points to local data space
	mov %dx,%fs

# 調用系統調用號對應的系統調用函數
	call sys_call_table(,%eax,4)	# 間接調用指定功能C函數
	pushl %eax						# 把系統調用返回值入棧
	
# 如果進程時間片(counter)用完或者狀態(state)非就緒,則執行調度程式
	movl current,%eax		# 取當前任務(進程)數據結構地址→eax
	cmpl $0,state(%eax)		# state
	jne reschedule
	cmpl $0,counter(%eax)	# counter
	je reschedule

# 中斷處理程式後半段,返回被中斷程式繼續執行。
ret_from_sys_call:
# 若被中斷程式為0號進程,直接返回。
	movl current,%eax		# task[0] cannot have signals
	cmpl task,%eax
	je 3f                   # 向前(forward)跳轉到標號3處退出中斷處理

# 若被中斷程式運行在內核態(例如其它可被中斷中斷程式),則直接返回
	cmpw $0x0f,CS(%esp)		# was old code segment supervisor ?
	jne 3f
	cmpw $0x17,OLDSS(%esp)	# was stack segment = 0x17 ?
	jne 3f

# 若被中斷程式為用戶進程,則先處理進程的信號
# 通過信號點陣圖,判斷產生的信號,然後調用do_signal執行對應的信號處理程式
	movl signal(%eax),%ebx	# 取信號點陣圖→ebx,每1位代表1種信號,共32個信號
	movl blocked(%eax),%ecx	# 取阻塞(屏蔽)信號點陣圖→ecx
	notl %ecx				# 每位取反
	andl %ebx,%ecx			# 獲得許可信號點陣圖
	bsfl %ecx,%ecx			# 從低位(位0)開始掃描點陣圖,看是否有1的位,若有,則ecx保留該位的偏移值
	je 3f					# 如果沒有信號則向前跳轉退出
	btrl %ecx,%ebx			# 複位該信號(ebx含有原signal點陣圖)
	movl %ebx,signal(%eax)	# 重新保存signal點陣圖信息→current->signal.
	incl %ecx				# 將信號調整為從1開始的數(1-32)
	pushl %ecx				# 信號值入棧作為調用do_signal的參數之一
	call do_signal			# 調用C函數信號處理程式(kernel/signal.c)
	popl %eax				# 彈出入棧的信號值
	
# 返回被中斷程式
3:	popl %eax				# eax中含有上面入棧系統調用的返回值
	popl %ebx
	popl %ecx
	popl %edx
	pop %fs
	pop %es
	pop %ds
	iret					# 特權級中斷返回指令

用戶棧與內核棧之間的切換

特權級發生變化時,會涉及到內核棧和用戶棧的切換。linux具有兩個特權級,內核態(0)和用戶態(3)。int指令可以從用戶態轉入內核態,iret指令可以從內核態返回用戶態。

image

用戶棧到內核棧

中斷引起CPU特權級從3級到0級的變化,此時CPU會進行用戶棧到內核棧的切換操作。

  1. 獲取內核棧記憶體地址信息。CPU從當前任務狀態段TSS(PCB)中取得新棧的段選擇符和偏移值,內核棧指針從TSS的ss0(選擇符)和esp0欄位中獲得。
  2. 將用戶棧地址信息保存在內核棧中。將用戶態棧指針和代碼地址信息ss、esp、cs、eip壓入內核棧中。
  3. 將ss、esp、cs、eip指向內核棧和代碼地址。

內核棧到用戶棧

iret指令引起CPU特權級從0級到3級的變化,此時CPU會進行內核棧到用戶棧的切換操作。

iret指令將先前壓入內核棧的用戶進程棧和代碼地址信息cs、esp、ss、esp信息從棧里彈出,載入到相應的寄存器中,重新執行用戶進程。

進程調度的實現機制

每個用戶進程有自己的內核棧,進程調度時,將棧寄存器指向需要運行的進程的內核棧,執行iret指令即可繼續運行該進程。

內核棧的切換

進程調度的通過內核棧之間的切換,實現進程之間的切換運行。為什麼每個進程都需要一個內核棧?進程需要保存運行狀態信息(各種寄存器信息),等待被調度程式選中運行。

image

進程切換

進程切換的實質在於進程狀態(上下文)的切換,即將CPU的當前進程狀態替換成新進程的狀態。被替換進程的進程狀態會保存在其對應的tss數據結構中,等待恢復運行。任務寄存器TR會保存當前任務的TSS指針,TSS數據結構總保存進程的運行狀態。

具體過程為:

  1. 當前進程通過中斷進入內核,用戶態ss、esp、cs、ip寄存器信息保存在內核棧中,切換到內核態運行,使用內核堆棧
  2. schedule調度程式時,將當前進程內核態運行信息保存在當前任務的tss數據結構中,然後切換到新進程的內核運行狀態,在內核中運行新的進程。
  3. 新運行的進程通過iret指令從內核態轉到用戶態運行,用戶態的運行狀態信息在其內核棧中。

image

參考

  • Linux 內核完全註釋 內核版本0.11 - 趙炯

PS:錯漏指出,請大佬指正,在評論區可交流學習。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上文,我們通過剖析一個最簡單的 Blazor WASM 項目,講明白了 Razor 文件是什麼,以及它被轉譯成 C#後長什麼樣子。也介紹了 Razor 中最簡單的一個語法:Razor Expression,也就是 Razor 表達式 本文將介紹兩個內容: 首先我們將書接上文,再介紹一丁點 Razor ...
  • 最近在做這個登錄功能介面,記錄一下 1、小程式端調用wx.login方法獲取code,後端使用WeChatAuth方法請求auth.code2Session介面使用appid、secret、js_code、grant_type:預設authorization_code獲取session_key、op ...
  • 對於語音識別,一般有實時語音識別和語音文件的識別處理等方式,如在會議、培訓等場景中,可以對錄製的文件進行文字的轉錄,對於轉錄文字的成功率來說,如果能夠轉換90%以上的正確語音內容,肯定能減輕很多相關語音文本編輯的繁瑣工作,而目前大多數語音轉錄的介面基本都能夠保證在這個成功率上,有些甚至超過98%以上... ...
  • Linux 0.11源碼閱讀筆記-文件管理 文件系統 生磁碟 未安裝文件系統的磁碟稱之為生磁碟,生磁碟也可以作為文件讀寫,linux中一切皆文件。 磁碟分區 生磁碟可以被分區,分區中可以安裝文件系統,常見的文件系統有fat32、ext2、ext4等。分區後的磁碟結構佈局如下圖,其中主引導扇區記錄了分 ...
  • 記憶體管理 Linux內核使用段頁式記憶體管理方式。 記憶體池 物理頁:物理空閑記憶體被劃分為固定大小(4k)的頁 記憶體池:所有空閑物理頁組成記憶體池,以頁為單位進行分配回收。並通過點陣圖記錄了每個物理頁是否空閑,點陣圖下標對應物理頁號。 分頁記憶體管理 虛擬頁:進程虛地址空間被劃分為固定大小(4k)的頁 分頁記憶體 ...
  • 一、在 CentOS 上安裝 Docker 引擎 Docker 支持 Mac Windows Linux 的三種安裝 官方文檔:https://docs.docker.com/ 1、系統要求 官網提示如果要安裝 Docker Engine, 需要一個CentOS 7 以及以上的穩定版本。 2、卸載舊 ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 PuTTY是一個Telnet、SSH、rlogin、純TCP以及串列介面連接軟體。 我們連接伺服器一般用ssh或者telnet,這種小工具非常多,今天來推薦putty, 最新版本下載地址:https://mirrors.aliyun.com/pu ...
  • 轉自:https://www.nerdfonts.com/https://www.nerdfonts.com/ 明確出處,如有侵權請及時聯繫刪除。 最近把開發環境換成了Windows 11,各個方面的使用還有點不習慣,不過經過了一天的配置,基本環境已經OK了。比較難受適應的是還是Terminal,在 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...