如果一个 C 程序可以直接在
硬件内核如何处理对此的资源分配
程序。
内核负责管理整个计算机的资源,包括硬件等资源。这意味着,为了让用户级应用程序能够访问硬件设备、写入终端或读取文件,它们必须向内核请求许可。正如@Marcus 所提到的,这是通过使用操作系统公开的系统调用来完成的。
但是,我不会说程序直接在硬件上运行因为它不直接与硬件交互,作为内核模块/驱动程序将。客户端程序将为系统调用设置参数,然后中断内核并等待内核服务程序发出的中断请求。
这就是为什么今天的操作系统被称为在保护模式下运行的原因,而不是过去它们在真实模式下运行的原因,并且程序可以,例如,直接弄乱硬件资源——并可能搞砸。
如果您尝试在 x86 汇编中编写一个简单的“hello world”程序,这种区别就会变得非常明显。我几年前写过并记录了this one,转载如下:
;
; 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)
注意程序如何设置写系统调用sys_write,然后指定写入位置的文件描述符stdout、要写入的字符串等等。
也就是说,程序本身并不执行写操作;它通过使用特殊的中断int 80h 来设置并要求内核代表它执行此操作。
一个可能的类比可能是你去一家餐馆。服务器将接受您的订单,但厨师将负责烹饪。在这个类比中,您是用户级应用程序,为您点餐的服务器是系统调用,厨房里的厨师是操作系统内核。
如果从 gcc 生成的可执行文件在纯机器中
可以理解的形式那么特权和非特权模式如何
工作吗?
从上一节开始,用户级程序总是在 user 模式下运行。当程序需要访问某些东西(例如终端、读取文件等)时,它会设置这些东西,就像上面的 sys_write 示例一样,并要求内核通过中断代表它完成。中断导致程序进入 kernel 模式并保持在那里,直到内核完成对客户端请求的服务——这可能包括完全拒绝它(例如,尝试读取用户无权访问的文件阅读)。
在内部,系统调用负责发出int 80h 指令。用户级应用只看到系统调用,这是客户端和操作系统之间的通用接口。
内核如何管理硬件资源的权限
程序可以不通过内核直接在硬件上运行吗?
如果您按照前面的说明进行操作,您现在可以看到内核充当看门人,并且程序通过使用int 80h 指令“敲门”。