系统调用期间的用户模式和内核模式切换

4
在Linux系统调用期间,以下哪些情况会发生:
  1. 用户模式进程被提升为内核模式并执行内核代码(中断服务例程),然后返回正常模式。换句话说,消耗CPU的是用户进程。
  2. 有一个内核进程始终在内核模式下运行。用户模式进程将任务(以系统调用形式)分派给内核进程。内核进程完成工作并将结果返回给用户模式进程。换句话说,此时用户进程处于空闲状态,而内核进程是消耗CPU的那个。
  3. 其他情况。

没有所谓的“内核进程”,只有内核内存空间,它是每个进程的一部分,因此更容易切换。如果它是一个单独的进程,你就必须从头开始重新映射内存。 - Sedat Kapanoglu
2个回答

3

这主要是1,但也有一点2。

从用户模式应用程序的角度来看,系统调用本身是同步进行的。 然而,通常情况下,系统调用没有所需的返回内容,因此会将进程置于睡眠状态。 这并不总是发生; 有些简单的系统调用确实是同步完成的。 但是,有些需要等待长时间运行的I/O任务才能完成。

内核具有处理异步事物的中断处理程序和内核线程。 例如,你的硬盘中断了系统,表示它最终检索到了你正在读取的文件。其中一个这些异步事件可以到来并唤醒您的进程,现在系统调用已经有了返回到用户空间所需的内容。

因此,看起来整个过程是同步发生的,但这只是一种假象。


这意味着内核进程/线程在为用户进程提供系统调用服务时也可以执行一些代码(消耗一些CPU周期)。由于内核线程/进程具有不同的pid,因此该CPU使用量将计入内核进程而不是用户进程。我正在对我的应用程序进行分析,发现一些内核工作线程消耗了一些CPU周期。我想知道是否是我的应用程序导致kworker线程进行了一些计算。如果我理解有误,请纠正我。 - Arpit Aggarwal
我不是很有信心,但我认为绝大部分时间应该正确地归因于您的进程。由 kworker 线程执行的任何操作都应被视为系统中其他事情的副作用,而不是您的应用程序的直接后果。虽然很难说。 - Jonathon Reinhart

2
为了让处理器进入内核(或另一个提升的)模式,必须通过中断或异常来实现。因为您在询问系统调用,所以我们正在处理异常。
[作为过度简化的风险,尤其是英特尔的奇怪行为...] 任何硬件异常(例如,访问冲突,除零,页面错误)都会导致处理器进入内核模式。每个异常都有一个由处理器定义的编号。当发生异常时,处理器分派到异常处理程序。通常,处理器具有定义异常处理程序数组的位置和长度的寄存器。当异常#2发生时,CPU调用数组中的第三个处理程序(0、1、2)。
处理器不变地具有触发特定目的异常的指令,例如调试和系统调用。
要进行系统调用,请调用引发异常的处理器指令,该异常将分派到执行系统调用的异常处理程序。在系统调用结束时,处理程序调用特殊的从异常/中断返回指令,将处理器返回到用户模式。
因此,您的#1在很大程度上是正确的。
在大多数操作系统中,您的#2完全错误。中断和异常由当前正在执行的进程处理(Linux使用不同的术语,但在功能上是相同的)。
如果您的进程读取磁盘,则在等待响应时可能会暂停。当中断发生时,另一个进程将正在运行,该中断表示YOUR磁盘I / O已完成。该进程将处理您的I / O中断。然后,它将您的I / O请求排队到您的进程,并将您的进程状态设置为可运行。下次调度您的进程运行时,它可以接收其已完成的I / O请求。

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