好吧,我的问题在标题中
众所周知,异常处理程序负责将用户模式切换到内核模式
这涉及某些汇编指令
据称这样做是为了防止应用程序使用访问受限的高特权指令和内存区域
用户模式应用程序不能自己执行这个用户内核切换吗?即在应用程序本身的常用函数例程中使用这些汇编指令?
如果是这样,那么我无法理解软件中断的意义以及与用户内核切换相关的所有安全注意事项
我们只需在我们的程序中实现该开关,瞧!我们现在处于内核模式
WTH
好吧,我的问题在标题中
众所周知,异常处理程序负责将用户模式切换到内核模式
这涉及某些汇编指令
据称这样做是为了防止应用程序使用访问受限的高特权指令和内存区域
用户模式应用程序不能自己执行这个用户内核切换吗?即在应用程序本身的常用函数例程中使用这些汇编指令?
如果是这样,那么我无法理解软件中断的意义以及与用户内核切换相关的所有安全注意事项
我们只需在我们的程序中实现该开关,瞧!我们现在处于内核模式
WTH
你犯了一个错误:用户唯一能做的就是调用一个可以执行特权指令的例程。这是由软件中断完成的。之所以称为中断,是因为原始用户模式程序在处理调用时停止。这样,用户态程序是完全无法执行特权的,但它可以调用内核中的中断例程。程序本身永远不会处于内核模式。
重点是安全。
用户态应用程序在有限的环境中工作。他们可以做自己的事情,但不能读或写任何没有明确分配给他们的东西。这个非常重要。整个现代操作系统的重点是保持应用程序分离。这主要是通过使用现代硬件提供的内存管理器单元来保证的。因此,典型的用户态应用程序无法访问任何内核内存,也无法“跳转”到任何地方。如果它被允许,将无法确定应用程序是否没有跳转到内核未预料到的地方并执行代码导致整个系统崩溃或从另一个应用程序窃取您的信用卡号。
当应用程序需要任何“在它自己的盒子之外”的功能时,它必须调用内核代码来完成它。但是怎么做?从应用程序的角度来看,任何地方都没有内核代码之类的东西。这就是为什么通常有一条“系统调用”(syscall)指令。它使当前代码流跳转到内核准备的指定位置以及它期望处理所有用户态请求的位置。由于系统调用与 IRQ、数据/预取和类似事件非常相似,因此硬件架构通常像此类事件一样对所有事物进行建模,通常称为“异常”。因此得名“软件中断”。
这有点简单,但确实如此。如果你想真正理解它,你必须熟悉异常、虚拟内存和类似的概念。
首先,我不太明白通过“手动”切换到内核模式想要获得什么。所以,你已经切换了,然后呢?你想下一步该做什么?如果您想访问不应在用户应用程序中访问的资源,那么这就是不允许它的全部意义,因为如果它被允许,那么您的应用程序将能够轻松地做如下令人讨厌的事情:
现在,如果您对上述任何操作都不感兴趣,那么您的应用就没有理由获得内核权限。
我承认,操作系统中存在某些错误以及我们认为我们希望通过获得所述访问权限来解决的错误,但这种情况很少见,而且很少有人能够在不破坏重要内容的情况下真正“修复”这些错误,所以可靠性和安全性问题超过了 1000 比 1 的“修复”操作系统中您不喜欢的东西的冲动。
至于中断和异常是切换到内核模式的方式,这只是一种有意义的常见实现。
中断必须在内核中处理,这就是为什么它们会在需要时进行切换。它们必须如此,因为只有内核和设备驱动程序知道如何处理触发中断的硬件。这就是操作系统的全部意义,抽象出硬件差异并为程序提供统一的 API 来做一些事情,使他们摆脱知道如何使用这个或那个显示器、声卡、网卡或打印机等的负担等等
软件中断只是搭载与硬件中断相同的机制,因为这样做很便宜。软件中断的主要用途是向操作系统请求一些工作/协助,可以理解的是,它们也需要切换,这就是硬件中断已经做的事情。
在 x86 平台上,硬件中断和ìnt
指令在 CPU 中产生几乎相同的响应,它们的处理方式非常相似。
对于这个系统调用功能,一些 CPU 提供了与中断无关的特殊指令。它们可能比在硬件中断之上实现的软件中断更快,或者它们可能带有软件中断不提供的一些有用的额外功能。
x86 指令sysenter
和syscall
. 它们针对从用户模式到内核模式的快速转换进行了优化。
一些异常与硬件中断具有相同的性质,例如页面错误异常。它也必须在内核中处理,因为这是操作系统用来实现虚拟磁盘内存的机制。操作系统需要访问磁盘上的内容以响应页面错误,然后更改页表,而您的应用程序本身不太可能做到这一点,让它访问诸如任意位置之类的重要内容并不是一件好事在磁盘或页表上自由。
其他异常用于控制应用程序的执行并通知操作系统出现问题,这使操作系统有机会解决问题或终止行为不端的应用程序,而不必将其保持在僵尸状态仍然消耗宝贵的资源,例如记忆。这些异常也需要在内核中处理,这是唯一的方法。
现在,您可能有兴趣在应用程序本身内处理应用程序的异常。某些操作系统允许您这样做。Windows 实现了它所称的Structured Exception Handling
(AKA SEH
),而 Linux 和 Unix 实现了signals
. 做任何一个通常仍然涉及首先处理内核中的异常,然后才将其反射回它的来源。这就是大多数 CPU 的实现方式。当异常首先被路由到内核中时,这样的实现既简单又便宜,并且它不会禁止任何东西,因为内核可以在此之上实现任何东西,包括 SEH 和信号。
无论如何,因为它是操作系统/内核为用户应用程序提供功能并确保安全性,并且两者往往齐头并进(因为操作系统/内核可以访问所有内容,而您的应用程序不应该和操作系统有时代表您的应用程序访问这些东西,想想礼貌:),这两个东西都在用户模式和内核模式之间的想象围栏后面。