我想准确理解什么是用户空间?我问的每个人都说:“任何不是内核的东西”。但对我来说这不是有形的。当我读到内核可以在用户空间或类似的东西上运行该驱动程序时;我无法想象会发生什么!因此,如果有人在这方面纠正我,我将不胜感激。
答案1
在一个概念层面上,内核是在“更特权”的硬件保护级别上运行的所有东西。这就像 x86 处理器上的环 0、ARM 上的系统模式、MIPS 上的内核模式、68xxx 上的管理程序模式等。内核通常是中断驱动的,要么是软件中断(系统调用),要么是硬件中断(磁盘驱动器、网络中断)卡、硬件定时器)。
在同一概念级别上,“用户空间”是以最低特权模式运行的(x86 CPU 上的环 3、ARM 或 MIPS 上的用户模式等)。用户态利用内核平滑微小硬件差异的方式,向所有程序提供相同的 API。例如,某些无线卡可能比其他无线卡具有额外的控制寄存器,或者包含更多或更少的用于传入数据包的板载缓冲区。驱动程序代码考虑了这些差异(有时通过忽略高级或不寻常的功能),并向所有程序提供相同的套接字 API。
某些处理器(例如 x86、VAX、Alpha AXP)具有两种以上的模式,但通用 Unix 架构不使用中间模式。
您看到在 Unix、Linux 或 *BSD 中运行的程序和进程都是用户空间。由于进程是可抢占的,因此您实际上永远不会看到内核运行,您只会看到副作用,例如read()
系统调用返回或信号处理函数运行。
为了回答您的具体问题,在 Unix、Linux、*BSD 中,“驱动程序”通常是一些小型软件,用于处理某些硬件的特定特性:网卡、磁盘驱动器、显卡。驱动程序软件几乎总是需要在 Ring 0/管理程序模式/内核空间中运行,以便能够访问硬件中断或硬件的映射内存等。驱动程序负责特定的硬件功能,并使该硬件符合内核代码关于硬件应如何工作的标准化或常规视图。因此,在用户态运行驱动程序需要内核向用户态程序显示映射内存或设备寄存器或中断或其他特殊功能等内容。这可能很棘手,因为设备可能需要的特殊功能不容易适应提供给用户程序的常见 Unix 风格 API。此外,调度也是一个问题,因为用户态程序通常不会快速响应中断。
答案2
大多数现代 CPU 都有一个核心或主管模式,以及受限的用户模式。这是CPU的硬件特性。 “Userland”是在用户模式下运行的代码的另一个名称。
这些模式之间的一大区别在于大多数现代 CPU 的 MMU 在这些模式下的工作方式。
MMU 允许内核重新排列 RAM 块(或页面),以便它们看起来以与 RAM 中物理顺序不同的顺序进行编码,并且还会导致用户模式代码陷阱或者 ”过错如果访问某些页面,则返回内核模式。用户模式无法更改 MMU 的操作,只有内核模式可以做到这一点。
因此,MMU 允许内核模式代码执行各种很酷的事情,例如:
- 将内存“安排”或“映射”到用户模式代码,以便此类代码认为它具有连续的 RAM。
- 实现动态内存管理方案,进程在尝试使用内存之前需要请求内存。
- 如果用户进程使用了不应该使用的内存,则停止用户进程。
- 如果可用内存不足,则将最少使用的页面交换到磁盘,并在进程尝试访问它们时将其交换回来。
您可以看到,MMU 与内核/用户模式一起是多任务操作系统的基石,使用这些工具可以创建一个可以处理更高级别事物(例如进程概念)的系统。内核为每个进程维护页表,并在切换到用户模式之前对 MMU 进行重新编程,并将控制权交给进程的时间片。进程获取内存之类的事情malloc
会导致内核修改 MMU 页表。
再说一次,用户模式不能对页表做任何事情(并且不需要知道它们存在),如果它需要内存,它需要称呼内核,这会导致从用户模式切换到内核模式。 CPU 提供了一种简单的机制,称为软件中断去做这个,Linux 内核还有其他更快的方法。
由于用户模式中存在这种保护,如果程序执行诸如崩溃或失控并覆盖自身之类的操作,内核可以停止该进程。在内核模式下,这种保护不存在,因此内核将停止工作,从而你的整个系统也将停止工作。当在内核模式下发生此类不可恢复的错误时,称为内核恐慌。看什么是“内核恐慌”?了解详情。
内核可以在用户态上运行该驱动程序
CPU 的内核或管理模式还阻止用户模式直接访问 I/O 设备,其想法是它必须调用内核来做到这一点。在 Linux 中,直接与设备对话的代码(它们在内核模式下运行)是设备驱动程序(一种内核模块,您可以使用lsmod
、insmod
、modprobe
和rmmod
) 等命令来操作它们。
如果您的设备驱动程序(在最简单的设置下在内核模式下运行)有一个错误并做了一些令人讨厌的事情,例如覆盖 RAM 中的随机内容(并且由于它处于内核模式,因此它可以不受限制地访问所有 RAM 并且可以覆盖),会发生什么内核本身)。如果我们能让设备驱动程序在用户模式下运行,这样它就不能对内核本身或其他进程做任何事情,那就太好了。
不幸的是,从用户模式切换到内核模式(称为上下文切换)很慢,因为基本上每个进程或内核本身都必须切换 CPU 的整个状态。因此,我们有两件事存在分歧:安全性或速度,因此这是一个争论点和设计点。
尝试在用户模式下做尽可能多的事情的内核被称为微内核,而Linux则相反,称为整体式的。 Linux 确实存在用户模式驱动程序(以 FUSE 为例),甚至还有一个框架这允许它。
答案3
根据 Bruce 所说,提供给内核的所有代码都必须可信。如果内核可以通过某种方式执行恶意代码,那么游戏就结束了。这就是用户执行代码和内核执行代码的权限分离发挥作用的地方。用户运行的代码不一定 100% 没有邪恶。它不直接由内核执行。
用户态程序只是与内核的公开部分交互,例如 API 和加载的模块。一个例子是iptables
。有几个内核模块(.ko)或“驱动程序”实际上完成了 的工作iptables
,它们是网络过滤框架。当您执行命令时,/sbin/iptables
您正在使用用户层组件,该组件又与加载到内核中的 netfilter 模块进行通信。这允许分离,以便内核不会无意中执行用户代码。
答案4
在 Unix/Linux 操作系统中,我们的区别在于用户空间和内核空间。这只是用户空间和内核所属位置的同义词。
你可以这样理解。您可以与用户空间中发生的所有事情进行交互。在内核空间中情况并非如此。守护进程、库和应用程序都属于用户空间。所有在操作系统内核之外运行的代码都属于用户空间(userland)。
内核空间是内核本身运行的地方。这是一个连 root 都无法访问的禁区。但是 root 用户可以通过内核提供的接口(procfs、sysfs)来操作一些内核参数。
系统内存是解释内核空间和用户空间之间差异的一个很好的例子。守护进程(在用户空间中运行)需要一些内存才能运行。内核管理所有可用的内存。守护进程从内核获取一些“虚拟内存”,守护进程不知道它是物理内存还是交换空间还是其他什么。内核决定进程获取哪种内存。因为内存管理发生在内核空间。内核空间中发生的其他事情包括进程调度、进程间通信、内存保护和管理、系统调用......
用户态到底是什么?
因此,用户态是守护进程在与操作系统资源(I/O、网络、内存、CPU 时间)交互时所做(或可以做)的事情。这些资源对内核空间中的进程是隐藏的。
简短的回答:
这就是飞行员的飞机驾驶舱。