从用户模式切换到内核模式

19
在我的操作系统课程中,我被问及从用户模式切换到内核模式是否是特权的。这不是特定于操作系统的。起初我认为是,但它似乎像一个巨大的进退两难。我参考了我的教科书:
硬件仅允许在内核模式下执行特权指令。... 切换到内核模式的指令是特权指令的例子。
因此,我们开始处于用户模式。要切换到内核模式需要一个特权指令。特权指令必须在内核模式下执行,因此我们必须切换到内核模式才能启用切换到内核模式。
我认为系统不允许用户直接将自身切换到内核模式,而是当用户试图执行另一个特权指令时由内核完成。正确吗?

那真的是一个打字错误吗? - denis631
5个回答

33
在用户模式下,你不能直接切换到内核模式。用户和内核之间的交互是通过系统调用完成的。每个系统调用都提供了一个定义好的服务。用户发送服务名称(通常是一个数字)和所需参数。
下面是一个真实世界的例子,展示了如何完成这个过程。这是x86 AT&T风格汇编语言。
它将系统调用名称移入EAX寄存器,并将指向参数的指针移入CPU的EBX寄存器,然后发出软件中断号42。中断处理程序会进行内核模式的切换。中断号在中断描述符表(IDT)中查找,并调用那里注册的函数,即系统调用处理程序。该处理程序在内核模式下执行。返回到用户模式后,代码将EAX的内容移动到变量ret中。
pok_ret_t pok_do_syscall (pok_syscall_id_t syscall_id, pok_syscall_args_t* args)
{
  pok_ret_t ret;
  uint32_t  args_addr;
  uint32_t  id;

  args_addr = (uint32_t) args;
  id        = (uint32_t) syscall_id;

  asm volatile ( "movl %1,%%eax  \n\t"
                 "movl %2,%%ebx  \n\t"
                 "int $42        \n\t"
                 "movl %%eax, %0 \n\t"
                 :"=g"(ret)
                 :"g"(id), "g"(args_addr)
                 : "%eax" , "%ebx"
               );
  return ret;
}

OS Dev wiki是了解这方面更多信息的好地方。

因此,您不仅可以切换到内核,还可以要求内核为您执行某些操作。然后内核会告诉您是否完成了该操作。


1
这是正确的答案,对我帮助很大。谢谢! - Christopher Wirt
是的,那是一个很好的答案,但是模式位呢?它什么时候会改变? - Baradwaj Aryasomayajula
@BaradwajAryasomayajula 你是指CR0.pe吗?这与你有什么关系呢?也许这是一个单独的问题。我无法给你一个精确的答案,但是由CPU执行的“int”指令会引发中断,从而启动内核模式切换。您可能需要查看英特尔手册以获取更多详细信息。 - Philipp
@Philipp 我了解到有一种叫作“模式位”的寄存器,只能在内核模式下访问。当 CPU 切换到内核模式时,它会将模式位更新为 0;而当它切换到用户模式时,它会将其更新为 1。 - Baradwaj Aryasomayajula
1
@BaradwajAryasomayajula,关于控制寄存器0位0(保护使能),请参阅英特尔手册Vol. 3A p. 2-16。如果您仍有疑问,请单独开启一个问题进行讨论。这里不是讨论此事的地方。 - Philipp

7
这是第8版中引入的错别字,并被保留在第9版中。在第七版第19页,它改为:

“切换到用户模式的指令是特权指令的一个例子。”

这显然更加合理易懂。

1
我不是很确定。第七版的勘误清楚地表明第八版(因此第九版)是正确的...... (也就是说,这在第七版中被确认为错误。) - Ephemera
@ephemera 维护勘误表的人可能是学生。 - PleaseHelp
1
切换到内核模式不需要特权,这样更有意义吗?(每个程序都可以轻松实现吗?) - Rptk99
1
没有任何程序可以切换到内核模式,系统在内核模式下启动并在中断时切换到它。在让程序执行之前,由引导系统(通常是操作系统)负责切换到用户模式,并确保中断不能由“每个程序”服务。如果有一条指令可以切换到内核模式,并且您需要处于内核模式才能使用它...那么这就是OP的推理,而且是正确的。 - user832146

3
通常有一组指令,不是真正意义上的转换到内核模式,而是请求系统服务。因此,这些指令会切换到内核模式,但仅在调用操作系统专门为用户代码调用而设置的某些功能代码时才会发生。
在大多数现代系统中,即使存在API层实现了特定功能,其中的一部分也可能会像上面那样调用操作系统。
但总的来说,用户代码无法做到等价于说“从这个点开始,我想在内核模式下运行”。

这意味着有一些指令会切换到内核模式,以调用其他系统服务,但问题仍未得到回答。如果切换到内核模式是特权指令,那么从用户模式下没有人可以执行该操作,对吗?我完全困惑了... - denis631

1
在用户空间,您通过系统调用向内核请求特权操作,内核会根据需要执行到内核模式的切换。用户使用API,内核执行特权操作。

0
我一直觉得作者对这个问题的回答令人困惑,并不会在操作系统考试中提出这样的问题(但对于讨论问题来说还是可以的)。在IBM 360/370大型机的旧时代,PSW(程序状态字)包括指向下一条指令的指针(也称为PC)、模式位(=1表示特权模式)和其他状态寄存器。当前的PSW保存在一个硬件寄存器中。有一个加载PSW(LPSW)指令,用于将新的PSW加载到这个寄存器中,由于它可以改变模式位等,因此是特权指令。中断是一种硬件机制,用于保存当前的PSW(通常是在用户模式下=0),并加载运行中断处理程序所需的特权模式下的PSW。因此,这是一种由硬件引起的切换,而不是通过执行LPSW指令来实现的。处理程序本身将执行LPSW指令,以加载其中一个保存的用户PSW。因此,对于这个“进退两难”的问题,答案是硬件机制将我们带入特权模式,之后特权的LPSW指令可以运行,以在稍后返回用户模式。后来为迷你计算机和微型计算机(即今天的工作站和个人电脑)发明的操作系统使用了不同的切换机制。在我所了解的所有操作系统机制中,用户可以通过发出任何系统调用间接进入特权模式,但这是一种自愿将控制权交还给处于特权模式(也称为监管模式或内核模式)的操作系统的方式。简而言之,用户不应直接更改模式位,因为那是操作系统管理的另一个硬件资源,而不是用户。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接