C和内存中的资源保护

shi*_*arg 5 c operating-system system-calls usermode kernel-mode

当我们编译一个C程序时,它只生成一些机器可理解的代码.这个代码可以直接在硬件上运行,从这个问题来讲.

所以我的问题是:

  1. 如果C程序可以直接在硬件上运行,那么内核如何处理该程序的资源分配?

  2. 如果从编译器生成的可执行文件是纯机器可理解的形式,那么特权和非特权模式如何工作?

  3. 如果程序可以直接在硬件上运行而不是通过内核,内核如何管理硬件资源的权限?

Mar*_*ler 5

虽然程序是在机器代码中,为了做不在自己的内存区域内的任何事情,它需要通过系统调用调用内核.

CPU实际上有一个代码特权的概念.非特权代码不能直接访问物理内存等; 它必须通过操作系统并要求它提供访问权限.

因此,每个程序都直接在CPU上运行,但这并不意味着它可以对硬件做任何事情 - 对此进行硬件测量.您需要做某些事情的特权就是其中之一.


cod*_*edd 5

如果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)
Run Code Online (Sandbox Code Playgroud)

注意程序如何设置write系统调用,sys_write然后指定写入位置的文件描述符,as,要写入stdout的字符串等.

换句话说,程序本身不执行写操作; 它设置了东西,并要求内核代表它使用一个特殊的中断来执行它int 80h.

这里可能有类比,当你去餐厅时.服务器将接受您的订单,但厨师将进行烹饪.在这个类比中,您是用户级应用程序,服务器命令的服务器是系统调用,厨房厨师是操作系统内核.

如果从gcc生成的可执行文件是纯机器可理解的形式,那么特权和非特权模式如何工作?

从上一节开始,用户级程序始终以用户模式运行.当程序需要访问某些东西(例如终端,读取文件等)时,它会像sys_write上面的示例那样进行设置,并要求内核代表它执行中断操作.中断导致程序进入内核模式并保持在那里直到内核完成服务客户端的请求 - 这可能包括完全拒绝它(例如,尝试读取用户没有权限读取的文件).

在内部,它是负责发出int 80h指令的系统调用.用户级应用程序只看到系统调用,这是客户端和操作系统之间的通用接口.

当程序可以直接在硬件上运行而不是通过内核时,内核如何管理硬件资源的权限?

如果您按照前面的说明进行操作,您现在可以看到内核充当网守,并且程序通过使用该int 80h指令"敲击"此门.