![除了使用系统调用之外,我们什么时候会跳转到进程虚拟内存的内核部分? (在Linux中)](https://linux22.com/image/140225/%E9%99%A4%E4%BA%86%E4%BD%BF%E7%94%A8%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E4%B9%8B%E5%A4%96%EF%BC%8C%E6%88%91%E4%BB%AC%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E4%BC%9A%E8%B7%B3%E8%BD%AC%E5%88%B0%E8%BF%9B%E7%A8%8B%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98%E7%9A%84%E5%86%85%E6%A0%B8%E9%83%A8%E5%88%86%EF%BC%9F%20%EF%BC%88%E5%9C%A8Linux%E4%B8%AD%EF%BC%89.png)
这是我之前的后续问题问题。
根据答案,系统调用是我们跳转到进程虚拟内存的内核部分的一个示例。
除了系统调用之外,正常进程(非内核)使用这部分虚拟内存的其他示例还有哪些?就像有没有任何函数调用可以直接跳转到这个内核部分或者..?
当我们跳转到这部分内存时,处理器是否会自动将内核模式位设置为1以便我们的进程访问这部分内存,或者不需要设置该位?
该内核部分内部的所有执行是否都不需要上下文切换到内核进程?
(我不想在评论中提出这些后续问题,所以我打开了另一个线程。)
答案1
在用户模式下运行的进程根本无法访问内核的地址空间。处理器可以通过多种方式切换到内核模式并运行内核代码,但它们都是由内核设置并在明确定义的上下文中发生:运行系统调用、响应中断或处理故障。系统调用不涉及直接调用内核代码;它们涉及一种特定于体系结构的机制,要求 CPU 将控制权转移到内核,以代表调用进程运行由其编号标识的特定系统调用。 LWN 有一系列文章解释其工作原理:系统调用剖析 第一部分,第二部分, 和附加内容。
如果进程尝试访问内核地址空间中的内存,它将切换到内核模式,但会由于故障而切换;然后,内核将因分段违规而终止该进程 (
SIGSEGV
)。在 32 位 x86 上,有是使用远调用切换到内核模式的机制,呼叫门;但 Linux 不使用它。 (它们依赖于特殊的代码段描述符,而不是调用内核地址。)
参见上文:您无法跳转到内核内存。在上述情况下,当转换到内核模式时,CPU 检查是否允许转换,如果允许,则使用适合所使用的体系结构的任何机制切换到内核模式。在 x86 Linux 上,这意味着从环 3 切换到环 0。
转换到内核模式不涉及进程的更改,所以是的,所有这一切都在没有上下文切换的情况下发生(由内核计算)。
答案2
1 & 2. 不,用户程序不能简单地使用跳转指令进入内核内存。不允许这样做。 CPU不会自动设置“内核位”以允许这样的跳转成功...(也许某些CPU具有这样的功能,但是安全的Linux端口会禁用此功能)
...实际上,由于您正在以没有权限的方式访问页面,因此您将进入内核:-)。它以受控方式进入,其工作原理与系统调用非常相似,但我们称之为“页面错误”。 CPU 将提供访问内核的详细信息。对于您描述的访问类型,内核会将其视为程序中的错误:-)。它将向您的程序发送致命信号(SIGSEGV)。
答案3
从技术上讲,内核内存可以映射到进程,不可读、只读或读写,甚至可能通过跳转到该内存中存储的代码来由进程执行。这是一种提高某些系统调用速度的技术,可以安全地运行代码来在进程中而不是在内核中处理系统调用。它还可以包括数据,例如包含内核提供的时钟值的内存地址,因此进程不必中断,因此系统可以进入内核。
进程也可以通过INT 0x80通过中断进入内核的系统调用,这是许多汇编程序员所熟悉的,但这当然不是内核可以提供的唯一机制。没有硬性规定内核和用户地址空间必须完全分开。
不管Linux采用什么方式,将内核代码和数据放入进程中在技术上肯定是可行的。出于与上下文切换和 TLB 相关的性能原因,Linux 也会例行地将内核内存放入进程中,但由于内核的许多区域都是敏感的,因此进程通常无法读取它们。