John P Asked: 2018-10-08 09:25:27 +0800 CST2018-10-08 09:25:27 +0800 CST 2018-10-08 09:25:27 +0800 CST 除了使用系统调用时,我们何时跳转到进程虚拟内存的内核部分?(在 Linux 中) 772 这是我上一个问题的后续问题。 根据答案,系统调用是我们跳转到进程虚拟内存的内核部分的一个例子。 除了系统调用之外,使用这部分虚拟内存的普通进程(非内核)还有哪些其他示例?比如有没有直接跳转到这个内核部分的函数调用或者..? 当我们跳转到这部分内存时,处理器是否自动将内核模式位设置为 1 以便我们的进程访问这部分,或者不需要设置该位? 这个内核部分内部的所有执行是否都不需要上下文切换到内核进程? (我不想在评论中问这些后续问题,所以我打开了另一个线程。) linux kernel 3 个回答 Voted Best Answer Stephen Kitt 2018-10-09T00:14:08+08:002018-10-09T00:14:08+08:00 在用户模式下运行的进程根本无法访问内核的地址空间。处理器切换到内核模式和运行内核代码有多种方式,但它们都是由内核设置并发生在明确定义的上下文中:运行系统调用、响应中断或处理故障。系统调用不涉及直接调用内核代码;它们涉及一种特定于体系结构的机制,要求 CPU 将控制权转移给内核,以代表调用进程运行由其编号标识的特定系统调用。LWN 有一系列文章解释其工作原理:系统调用剖析 第一部分、第二部分和附加内容。 如果一个进程试图访问内核地址空间中的内存,它将切换到内核模式,但由于故障;然后内核将终止具有分段冲突的进程 ( SIGSEGV)。 在 32 位 x86 上,有一种使用远调用、调用门切换到内核模式的机制;但Linux不使用它。(而且它们依赖于特殊的代码段描述符,而不是调用内核地址。) 见上文:你不能跳入内核内存。在上述情况下,当转换到内核模式时,CPU 检查是否允许转换,如果允许,则使用适合所使用架构的任何机制切换到内核模式。在 x86 Linux 上,这意味着从 ring 3 切换到 ring 0。 转换到内核模式不涉及进程的更改,所以是的,所有这一切都发生在没有上下文切换的情况下(由内核计算)。 sourcejedi 2018-10-08T14:42:49+08:002018-10-08T14:42:49+08:00 1 & 2. 不,用户程序不能简单地使用跳转指令进入内核内存。不允许这样做。CPU 不会自动设置“内核位”以允许这样的跳转成功......(也许某些 CPU 具有这样的功能,但安全的 Linux 端口会禁用此功能) ...实际上,由于您正在以您无权访问的方式访问页面,因此您将进入内核:-)。它以受控方式进入,它的工作方式与系统调用非常相似,但我们称其为“页面错误”。CPU 将提供访问内核的详细信息。使用您描述的访问类型,内核会将其视为程序中的错误:-)。它将向您的程序(SIGSEGV)发送一个致命信号。 Mark Smith 2021-04-19T12:19:40+08:002021-04-19T12:19:40+08:00 从技术上讲,内核内存可以映射到进程,不可读,只读或读写,甚至可能通过跳转到存储在该内存中的代码由进程执行。这可以是一种提高某些系统调用速度的技术,在这些系统调用中运行代码来处理进程而不是内核中的系统调用是安全的。它还可以包含诸如内存地址之类的数据,其中包含内核提供的时钟值,因此进程不必中断,因此系统可以进入内核。 进程也可以通过INT 0x80中断进入内核的系统调用,这是很多汇编程序员所熟悉的,但肯定不是内核能够提供的唯一机制。没有硬性规定内核和用户地址空间必须完全分开。 不管 Linux 使用什么方法,将内核代码和数据放入进程中肯定在技术上是可行的。由于与上下文切换和 TLB 相关的性能原因,Linux 也经常将内核内存放入进程中,但由于内核的许多区域都是敏感的,因此进程通常无法读取它们。
在用户模式下运行的进程根本无法访问内核的地址空间。处理器切换到内核模式和运行内核代码有多种方式,但它们都是由内核设置并发生在明确定义的上下文中:运行系统调用、响应中断或处理故障。系统调用不涉及直接调用内核代码;它们涉及一种特定于体系结构的机制,要求 CPU 将控制权转移给内核,以代表调用进程运行由其编号标识的特定系统调用。LWN 有一系列文章解释其工作原理:系统调用剖析 第一部分、第二部分和附加内容。
如果一个进程试图访问内核地址空间中的内存,它将切换到内核模式,但由于故障;然后内核将终止具有分段冲突的进程 (
SIGSEGV
)。在 32 位 x86 上,有一种使用远调用、调用门切换到内核模式的机制;但Linux不使用它。(而且它们依赖于特殊的代码段描述符,而不是调用内核地址。)
见上文:你不能跳入内核内存。在上述情况下,当转换到内核模式时,CPU 检查是否允许转换,如果允许,则使用适合所使用架构的任何机制切换到内核模式。在 x86 Linux 上,这意味着从 ring 3 切换到 ring 0。
转换到内核模式不涉及进程的更改,所以是的,所有这一切都发生在没有上下文切换的情况下(由内核计算)。
1 & 2. 不,用户程序不能简单地使用跳转指令进入内核内存。不允许这样做。CPU 不会自动设置“内核位”以允许这样的跳转成功......(也许某些 CPU 具有这样的功能,但安全的 Linux 端口会禁用此功能)
...实际上,由于您正在以您无权访问的方式访问页面,因此您将进入内核:-)。它以受控方式进入,它的工作方式与系统调用非常相似,但我们称其为“页面错误”。CPU 将提供访问内核的详细信息。使用您描述的访问类型,内核会将其视为程序中的错误:-)。它将向您的程序(SIGSEGV)发送一个致命信号。
从技术上讲,内核内存可以映射到进程,不可读,只读或读写,甚至可能通过跳转到存储在该内存中的代码由进程执行。这可以是一种提高某些系统调用速度的技术,在这些系统调用中运行代码来处理进程而不是内核中的系统调用是安全的。它还可以包含诸如内存地址之类的数据,其中包含内核提供的时钟值,因此进程不必中断,因此系统可以进入内核。
进程也可以通过INT 0x80中断进入内核的系统调用,这是很多汇编程序员所熟悉的,但肯定不是内核能够提供的唯一机制。没有硬性规定内核和用户地址空间必须完全分开。
不管 Linux 使用什么方法,将内核代码和数据放入进程中肯定在技术上是可行的。由于与上下文切换和 TLB 相关的性能原因,Linux 也经常将内核内存放入进程中,但由于内核的许多区域都是敏感的,因此进程通常无法读取它们。