【问题标题】:User mode and kernel mode switching during system calls系统调用期间的用户模式和内核模式切换
【发布时间】:2017-09-02 18:50:40
【问题描述】:

从广义上讲,在 linux 系统调用期间会发生以下哪些情况。

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

【问题讨论】:

  • 没有“内核进程”,只有内核内存空间,这是每个进程的一部分,因此更容易切换。如果它是一个单独的过程,您必须从头开始重新映射内存。

标签: linux linux-kernel operating-system kernel


【解决方案1】:

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

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

内核具有异步处理事物的中断处理程序和内核线程。例如,您的硬盘驱动器中断了系统,表明它最终检索到了您正在阅读的文件。这些异步事件之一可能会出现并唤醒您的进程,因为系统调用具有返回用户空间所需的内容。

所以看起来整个过程是同步发生的,但那只是一种错觉。

【讨论】:

  • 这意味着内核进程/线程在为用户进程提供系统调用的同时也可以执行一些代码(消耗一些CPU周期)。由于内核线程/进程具有与用户进程不同的 pid,因此 CPU 使用率将计入内核进程而不是用户进程。我实际上是在分析我的应用程序,我看到一些内核工作线程消耗了一些 CPU 周期。我想知道我的应用程序是否导致 kworker 线程进行一些计算。如果我错了,请纠正我。
  • 我不是很自信,但我想说绝大多数时间应该正确地计入您的流程。 kworker 线程所做的任何事情都应该被认为是系统中发生的其他事情的副作用,而不是您的应用程序的直接后果。不过很难说。
【解决方案2】:

为了让处理器进入内核(或其他提升的)模式,它必须通过中断或异常来实现。因为您在询问系统调用,所以我们正在处理异常。

[由于过于简单化的风险,尤其是英特尔的陌生...] 任何硬件异常(例如,访问冲突、被零除、页面错误)都会导致处理器进入内核模式。每个异常都有一个由处理器定义的编号。当发生异常时,处理器会分派给异常处理程序。通常,处理器具有定义异常处理程序数组的位置和长度的寄存器。当异常 #2 发生时,CPU 调用数组 (0, 1, 2) 中的第三个处理程序。

处理器总是有针对特定目的触发异常的指令,例如调试和系统调用。

要进行系统调用,您调用会导致异常的处理器指令,该异常会分派给执行系统调用的异常处理程序。在系统调用结束时,处理程序调用从异常/中断指令中返回的特殊返回,将处理器返回到用户模式。

因此,您的 #1 在很大程度上是正确的。

您的#2 在大多数操作系统中是完全错误的。中断和异常由当前正在执行的进程处理(Linux 使用不同的术语,但在功能上是相同的)。

如果您的进程读取磁盘,它可能会在等待响应时挂起。当中断发生时,另一个进程将运行,表明您的磁盘 I/O 已完成。该进程将处理您的 I/O 的中断。然后它将您的 I/O 请求排队到您的进程,并将您的进程状态设置为可运行。下次您的进程计划运行时,它可以获取完成的 I/O 请求。

【讨论】:

    猜你喜欢
    • 2018-11-01
    • 1970-01-01
    • 2021-08-15
    • 2013-10-04
    • 2010-10-23
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 2015-12-12
    相关资源
    最近更新 更多