【发布时间】:2011-07-10 13:50:54
【问题描述】:
由于 CPU 在用户/内核模式下运行,我想知道这是如何由内核决定的。我的意思是,如果调用 sys 调用,内核会代表进程执行它,但是内核如何知道它是在内核模式下执行的呢?
【问题讨论】:
-
也许你的意思是用户上下文/进程上下文与内核上下文/中断上下文?
标签: linux-kernel
由于 CPU 在用户/内核模式下运行,我想知道这是如何由内核决定的。我的意思是,如果调用 sys 调用,内核会代表进程执行它,但是内核如何知道它是在内核模式下执行的呢?
【问题讨论】:
标签: linux-kernel
您可以通过代码段寄存器 (CS) 中设置的权限级别来判断您是处于用户模式还是内核模式。从 RIP 或 EIP 寄存器(指令指针寄存器取决于您分别是 x86_64 还是 x86)指向的内存加载到 CPU 中的每条指令都将从当前代码的全局描述符表 (GDT) 中描述的段中读取-段描述符。代码段描述符的低两位将确定代码正在执行的当前特权级别。当进行系统调用时(通常通过软件中断完成),CPU 将检查当前特权级别,如果它处于用户模式,则将当前代码段描述符交换为内核级别的描述符,由下式确定系统调用的软件中断门描述符,以及进行堆栈切换并将当前标志、用户级 CS 值和 RIP 值保存在这个新的内核级堆栈上。当系统调用完成时,用户模式的 CS 值、标志和指令指针(EIP 或 RIP)值从内核堆栈中恢复,并且堆栈切换返回到当前执行进程的堆栈。
【讨论】:
The lower two-bits of the code segment descriptor 时,实际上不是你指的代码段选择器吗?
这个术语被称为“监督者模式”,它也适用于 x86/ARM 和许多其他处理器。
阅读本文(仅适用于 x86 CPU):
http://en.wikipedia.org/wiki/Ring_(computer_security)
Ring 0 到 3 是 x86 CPU 的不同权限级别。通常只使用 Ring0 和 3(内核和用户),但现在 Ring 1 找到了用途(例如,VMWare 用它来模拟客户对 ring 0 的执行)。只有 Ring 0 拥有运行某些特权指令(如 lgdt 或 lidt)的完全权限,所以在汇编级别的一个很好的测试当然是执行这些指令,看看你的程序是否遇到任何异常。
阅读本文以真正确定您当前的权限级别(查找 CPL,这是 Jason 答案的图示):
http://duartes.org/gustavo/blog/post/cpu-rings-privilege-and-protection
【讨论】:
这是一个简单的问题,不需要上面提供的任何专家评论..
问题是 CPU 如何知道它是内核模式还是用户模式。 答案是“模式位”……
它是cpu 寄存器组的状态寄存器中的一个位。 当“mode bit=0”时,,,,它被认为是内核模式(也称为,监控模式,特权模式,保护模式......和许多其他......) 当“mode bit=1”时,它被认为是用户模式......并且用户现在可以在没有任何特殊内核中断的情况下执行其个人应用程序。
这么简单……不是吗??
【讨论】:
内核代码仅在内核模式下执行。没有办法,内核代码可以在用户模式下执行。当应用程序调用系统调用时,会产生一个陷阱(软件中断),模式将切换到内核模式,系统调用的内核实现将被执行。完成后,内核将切换回用户模式,用户应用程序将继续在用户模式下处理。
【讨论】:
一般来说,如果它正在运行内核代码,则它处于内核模式。从用户空间到内核模式的转换(比如系统调用)会导致发生上下文切换。作为此上下文切换的一部分,CPU 模式已更改。
【讨论】: