我了解操作系统的一些复杂内部,但在理解内核和用户空间方面还有很大差距。
我现在将解释我是如何理解这一点的。
首先,我们有RAM
一个例子8GB
,这是平面内存,可以借助CPU
或DMA
机制访问任何一块内存。
当系统启动时,在初始步骤引导加载程序被加载到内存中,但在这个阶段我们的内存是原始的,我们没有 的概念Virtual Memory
,因为内核提供了这样的功能。
还有两种模式real mode
,protected mode
我在这里有疑问。
据我所知,这些模式是CPU功能。主要区别在于,在保护模式下,进程被隔离在自己的内存空间中……但是这是如何工作的呢?进程只是操作系统概念,在这个阶段real
,protected mode
我们没有任何操作系统加载到内存中,我们的内存只是可以从其他设备访问的硬件,或者例如加载到内存中的BIOS可以访问内存的任何区域,但是这不是一个进程,只是0和1加载到内存的某个地址,CPU一个接一个地读取每一条指令并执行它们......
例如,将内核加载到内存中后,内核从0x000000 to 0x000fff
其他所有内存中获取内存,这是可用于程序的空闲内存。现在我们已经将主程序加载到内核内存中,但这只是 CPU 正在执行的指令列表。
据我了解,内核设置了所有必要的服务、管理器……现在内核提供了使用可用内存的 API,即(RAM 大小 - 内存中的内核大小 - + 不同的中断处理程序和其他内容)。还有一个功能是CPU
特权模式,这只是CPU
寄存器中的一个标志,用于控制对设备的访问,如果当前权限不足以访问设备,cpu 会触发中断或其他什么。
我对吗 ?
谁控制着这面旗帜?例如,如果来自用户空间的代码进入内核模式,那么该标志设置为高特权,为什么用户程序无法访问整个内存并做坏事?
另一个概念是system call
。系统调用用于要求较低的功能,仅在特权模式下可用。
什么是真正的系统调用,每个人都知道,glibc
但这只是一个使用的包装器,我们如何知道需要系统调用的内存地址。我的意思是,例如进程想要进行系统调用,glibc 如何知道将其放在哪里 IP (instruction pointer)
或者如何完成以进行系统调用。
对我来说最难理解的事情之一是内核和用户空间一起工作。有很多图片和图表,其中内核空间和用户空间就像两个单独工作的人,并在需要时 User space guy
寻求帮助。Kernel guy
但是停下来,发生了什么事?考虑single CPU system
我们一次只执行一条指令。没有并行任务,我们只有一个CPU。
它在内核和用户空间方面是如何工作的。如果我们只有 CPU,用户模式到内核模式的切换之类的事情让我大吃一惊
请帮助我理解这些东西,我突出了我的问题,我试图找到答案,但仍然没有成功。也许我错过了一些很棒的文章,所以我将不胜感激任何帮助,谢谢。
答案1
忘掉实模式吧,这只是 x86 架构的一个细节,只是为了与 1980 年代的处理器兼容。
处理器确实有一个标志来指示当前的特权级别。该标志的详细信息因处理器类型而异,但为了简单起见,只需将其视为两个设置:用户和内核。
有一些处理器指令可以更改特权级别。对于安全来说最重要的是进入更高的权限级别也会跳转到预定义的地址。该地址可能位于仅允许内核代码修改的寄存器中,或者位于内核(通过 MMU)配置为在用户模式下不可访问的内存中。该地址的代码会仔细验证用户代码发出的请求,它不会接受来自用户代码的任意请求。
通常有几种方法可以获得更高的权限,至少三种:系统调用(当用户代码显式切换到内核模式时)、中断(当外设向处理器发出信号它应该做某事时)和陷阱(当处理器尝试执行无效的cide,例如访问未映射的内存或未知指令)。
在系统调用中,用户代码不指定跳转到哪里,它只是发出系统调用指令,然后处理器确定跳转到哪里。为了确定调用哪个系统调用,内核代码查看寄存器的内容:通常有一个寄存器包含系统调用号,内核中的系统调用调度程序在表中查找该编号。