簡體   English   中英

C和內存中的資源保護

[英]C and resource protection in memory

當我們編譯一個C程序時,它只生成一些機器可理解的代碼。 這個代碼可以直接在硬件上運行,從這個問題來講

所以我的問題是:

  1. 如果C程序可以直接在硬件上運行,那么內核如何處理該程序的資源分配?

  2. 如果從編譯器生成的可執行文件是純機器可理解的形式,那么特權和非特權模式如何工作?

  3. 如果程序可以直接在硬件上運行而不是通過內核,內核如何管理硬件資源的權限?

雖然程序是在機器代碼中,為了做不在自己的內存區域內的任何事情,它需要通過系統調用調用內核。

CPU實際上有一個代碼特權的概念。 非特權代碼不能直接訪問物理內存等; 必須通過操作系統並要求它提供訪問權限。

因此,每個程序都直接在CPU上運行,但這並不意味着它可以對硬件做任何事情 - 對此進行硬件測量。 您需要做某些事情的特權就是其中之一。

如果C程序可以直接在硬件上運行,那么內核如何處理該程序的資源分配。

內核負責管理整個計算機的資源,包括硬件等資源。 這意味着,要使用戶級應用程序能夠訪問硬件設備,寫入終端或讀取文件等內容,他們必須向內核請求許可。 這是通過使用OS公開的系統調用來完成的,如@Marcus所述。

但是,我不會說程序直接在硬件上運行,因為它不會直接與硬件交互,就像內核模塊/驅動程序那樣。 客戶端程序將設置系統調用的參數,然后中斷內核並等待內核服務程序發出的中斷請求。

這就是為什么今天的操作系統被稱為以受保護模式運行的原因,而不是過去他們以實模式運行的程序,例如,程序可能會直接亂用硬件資源 - 並且可能會搞砸。

如果你嘗試在x86程序集中編寫一個簡單的“hello world”程序,這種區別就會變得非常明顯。 我幾年前寫過並記錄了這個 ,轉載如下:

;
; This program runs in 32-bit protected mode.
;  build: nasm -f elf -F stabs name.asm
;  link:  ld -o name name.o
;
; In 64-bit long mode you can use 64-bit registers (e.g. rax instead of eax, rbx instead of ebx, etc.)
; Also change "-f elf " for "-f elf64" in build command.
;
section .data                           ; section for initialized data
str:     db 'Hello world!', 0Ah         ; message string with new-line char at the end (10 decimal)
str_len: equ $ - str                    ; calcs length of string (bytes) by subtracting the str's start address
                                            ; from this address ($ symbol)

section .text                           ; this is the code section
global _start                           ; _start is the entry point and needs global scope to be 'seen' by the
                                            ; linker --equivalent to main() in C/C++
_start:                                 ; definition of _start procedure begins here
    mov eax, 4                   ; specify the sys_write function code (from OS vector table)
    mov ebx, 1                   ; specify file descriptor stdout --in gnu/linux, everything's treated as a file,
                                             ; even hardware devices
    mov ecx, str                 ; move start _address_ of string message to ecx register
    mov edx, str_len             ; move length of message (in bytes)
    int 80h                      ; interrupt kernel to perform the system call we just set up -
                                             ; in gnu/linux services are requested through the kernel
    mov eax, 1                   ; specify sys_exit function code (from OS vector table)
    mov ebx, 0                   ; specify return code for OS (zero tells OS everything went fine)
    int 80h                      ; interrupt kernel to perform system call (to exit)

注意程序如何設置write系統調用sys_write ,然后指定寫入位置的文件描述符, stdout ,要寫入的字符串等等。

換句話說, 程序本身不執行寫操作; 它設置了內容,並要求內核代表它使用特殊的中斷, int 80h

這里可能有類比,當你去餐廳時。 服務器將接受您的訂單,但廚師將進行烹飪。 在這個類比中,您是用戶級應用程序,服務器命令的服務器是系統調用,廚房廚師是操作系統內核。

如果從gcc生成的可執行文件是純機器可理解的形式,那么特權和非特權模式如何工作?

從上一節開始,用戶級程序始終以用戶模式運行。 當程序需要訪問某些東西(例如終端,讀取文件等)時,它會像上面的sys_write示例那樣進行設置,並要求內核代表它執行中斷操作。 中斷導致程序進入內核模式並保持在那里,直到內核完成服務客戶端的請求 - 這可能包括完全拒絕它(例如,嘗試讀取用戶沒有權限讀取的文件)。

在內部,系統調用負責發出int 80h指令。 用戶級應用程序只能看到系統調用,這是客戶端和操作系統之間的通用接口。

當程序可以直接在硬件上運行而不是通過內核時,內核如何管理硬件資源的權限?

如果您按照前面的說明進行操作,您現在可以看到內核充當網守 ,並且程序通過使用int 80h指令來“敲擊”此門。

內核如何處理該程序的資源分配

內核提供了分配內存,執行I / O(寫入屏幕,與網絡/聲卡交互)等功能和機制,稱為系統調用用戶程序。 這些系統調用是內核和用戶程序之間的接口,在硬件和用戶程序之間。

特權模式和非特權模式如何工作?

用戶程序處於非特權模式(用戶空間),而內核以特權模式(內核空間)運行。 用戶不可信任,因此如果他搞砸了(例如,訪問更高權限的內存或取消引用空指針),他就會被阻止(例如,通過分段錯誤和以下程序終止)。

另一方面,內核以特權模式運行。 它可以做任何想做的事情:寫入用戶空間程序,從用戶程序竊取數據(如密碼),寫入處理器的固件 - 一切。 此外,有不同種類的內核:單片內核和微內核是最重的(這個詞是否存在?)使用的內核。

Linux(由Linus Torvalds發起)是單片內核的一個例子。 在這里,內核是一個大系統,每個內核代碼都可以最終訪問系統。

Minix(由Andrew S. Tanenbaum發起)是微內核的一個例子。 可以訪問所有內容的部分相當小。 它只包含必須具有特權的功能(管理MMU,訪問硬件)等。其他功能,如文件系統,在非特權模式下運行,通過用戶空間中常用的保護機制保護它們免受可能的錯誤(Unprivileged)模式),像分段錯誤。

有關單片內核和微內核的優點/缺點的有趣讀物是Linus Torvalds(當時創建操作系統的人)與Andrew S. Tanenbaum(當時是CS的老師)之間的爭論 ;寫了一些很棒的書,BTW)。

程序可以直接在硬件上運行而不是通過內核運行

它確實直接在硬件上運行,由CPU執行。 但是,它不能像內存那樣直接訪問某些資源 ,並且為了訪問這些資源, 需要與內核進行交互。 與DOS之類的早期操作系統相比,這是主要改進之一(可能是虛擬處理器,也就是流程):用戶空間程序不能直接在硬件上運行。 如果他們可以的話,他們可能會因為無法修復的原因(故意 - 像病毒,或無意中)而弄亂整台機器。 相反,如本答案開頭所述,使用系統調用。

在DOS中,您可以選擇使用OS提供的例程(通常是IV中的陷阱(中斷向量,偏移(和物理內存地址)到實模式IDT(中斷描述符表))0x21(通過int 0x21 / int 21h調用) int 21h ),而ax包含一個識別系統調用的功能號1 )。 大致相同的機制,如今可用嚴格執行。 可以覆蓋整個操作系統,用自己的程序替換它並銷毀機器(例如,將隨機值加載到CMOS寄存器中)。 也可以繞過操作系統,使用BIOS提供的例程。


1我在這里故意使用“呼叫系統”而不是“系統呼叫”。 這里,系統調用僅表示從用戶空間到內核空間的請求,以便為它做一些事情。 由於DOS(即實模式)沒有提供用戶空間和內核空間之間的真正區別,因此它實際上沒有系統調用。

所以我的第一個問題是,如果C程序可以直接在硬件上運行,內核如何處理該程序的資源分配。

CPU在執行代碼時帶有特權概念。 例如,在x86上有一個允許代碼訪問任何資源的實模式 ,以及一個代碼在不同安全環中執行的保護模式 大多數操作系統將切換到保護模式,其中數字較低的環意味着更高的權限。

內核通常在Ring 0中執行,它可以直接訪問硬件,而用戶程序在Ring 3中運行,這限制了訪問。 當用戶程序需要訪問特權資源時,CPU通過系統調用指令(例如x86-64匯編中的syscall )隱式或直接調用具有特權的操作系統。

如果從gcc生成的可執行文件是純機器可理解的形式,那么特權和非特權模式如何工作?

同樣,CPU會檢查內存訪問等內容。 因此,例如,如果程序試圖訪問它沒有權限的虛擬地址 ,則操作系統捕獲無效頁面訪問並且通常表示該過程(即SIGSEGV )。

當程序可以直接在硬件上運行而不是通過內核時,內核如何管理硬件資源的權限?

CPU必須通過特定的控制寄存器和表直接與操作系統交互。 例如,虛擬地址頁表的地址存儲在x86的CR3寄存器中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM