【问题标题】:How OS manages the process control block associated with a process?操作系统如何管理与进程关联的进程控制块?
【发布时间】:2022-10-14 08:05:04
【问题描述】:

我目前正在学习操作系统课程中的进程。我对流程的实际工作方式有点困惑。 根据我的理解

  1. 当我们双击一个可执行文件(假设是单线程的)时,会为这个新进程创建一个进程控制块,并在主内存中为进程分配一些空间。
  2. 然后是短期调度程序,将进程分派给 CPU(假设为单处理器系统)。
  3. CPU 执行进程并在阻塞它之前(以防发生中断或进程请求某些 I/O),将 CPU 的内容保存在进程控制块中。然后进程被发送到就绪队列。

    我的第一个问题是,这些 PCB 存放在哪里?形成我从其他网站上阅读的内容,因为PCB中的信息非常重要,操作系统将其保存在内核空间中,但其他一些网站说PCB存储在内核堆栈(在用户模式下无法访问),即位于与进程相同的地址空间(可能一个进程有两个堆栈,一个用户堆栈和一个内核堆栈)。那么实际上PCB存储在哪里?

    操作系统如何知道进程与其PCB之间的映射?操作系统如何知道与 PCB 相关的进程的物理位置。我假设因为 PCB 包含内存管理信息(如基址寄存器和堆栈寄存器的值),所以我的假设是否正确?

    我的最后一个问题是什么是进程表?信息处理表存储什么。 (我猜他们存储 pid 和指向进程 PCB 的指针)

    很抱歉提出这样一个基本问题,但我找不到任何令人满意的资源。 :(

    编辑1:进行了更多研究,发现操作系统同时使用内核堆栈(确实与进程位于同一地址空间下)和PCB。但事实证明,内核堆栈不存储 PCB,它只是将寄存器的内容存储在 CPU 内(在这里回答: During a context switch, does the OS use PCB or kernel stack to restore registers? 。所以问题仍然存在,PCB 实际存储在哪里?

    编辑 2:在研究了更多并研究了几本书之后,似乎所有的 PCB 实际上都存储在一个叫做调度队列的东西上。这些队列确实保存在系统空间中(不在内核堆栈上)并包含 PCB。有很多调度队列,如就绪队列、等待队列、中间队列(用于存储换出进程的信息)、I/O 队列和最后的作业队列。如果一个进程没有被执行,它的 PCB 将存储在这些队列之一中。事实证明,PCB确实存储了进程的基地址和对进程页表的引用等信息。虽然我仍然不确定进程表的作用是什么。

【问题讨论】:

  • 每个操作系统都不一样。没有理由浪费时间在关于每个人应该如何调用某个数据结构的术语细节上。操作系统开发的术语不是那么标准化。无论如何,操作系统不需要将PCB与进程的物理位置相关联,因为PCB就是进程。操作系统不理解什么是进程,因为它不是人类。它是在计算机中运行的代码。它盲目地获取PCB中的数据并根据已经编写的逻辑(其代码)将其放入适当的寄存器中。
  • 使用哪个 PCB 取决于调度策略。

标签: process operating-system scheduling


【解决方案1】:

您的操作系统课程似乎是经典的课程,作者向您提供的信息并不总是正确的,而且所使用的术语并非随处可见且令人困惑。总体而言,操作系统设计将根据操作系统的运行位置和用途而有所不同。每个操作系统开发团队对于不同的事物都有不同的术语。您了解的某些数据结构可能根本不会使用。

话虽如此,是否有内核堆栈和用户堆栈,寄存器存储在哪里,PCB 存储在哪里等等,都是如此不重要和多变的,以至于它甚至不是操作系统课程应该提及的信息。课程应该只提到信息应该保存在某个地方。

一般来说,Linux内核有一个用户态堆栈和一个内核态堆栈。它还将有一个堆栈用于每个内核的中断(不绑定到一个进程)。在 Linux 上,进程有一个 PCB,但内核在线程上工作。属于同一进程的每个线程共享相同的虚拟地址空间。 Linux 内核会将每个进程绑定到一个内核。这是由于内核靠近物理内存的某些部分(在 x86-64 上称为 NUMA)。 ACPI 表提供有关哪个范围的物理内存更接近某个内核的信息。如果内核想要更改一个线程的核心,它会使其执行速度变慢,因为它的内存将被分配到另一个核心的 NUMA 节点中。

现代 64 位 CPU 的虚拟地址空间 (VAS) 是巨大的(超过 200k GB)。所有线程都可以访问它的下半部分,因为内核保留了上半部分。线程和内核的指令包含将由页表翻译的虚拟地址。内核的工作是确保页表将虚拟地址转换为可用的物理内存。例如,在具有 8GB RAM 的计算机上,翻译必须低于 8GB。还有需要考虑的 NUMA 节点。

因此,在 Linux 上,PCB 存储在 VAS 的上半部分。在 x86-64 上,VAS 的上半部分是通过在页表中切换标志来实现的。这意味着,当内核更改 CR3 寄存器(指向 x86 的第一个页表级别的寄存器)时,不会刷新 TLB(翻译缓存)的这部分。现代 TLB 中还支持 PCID(进程 ID)。

如果您有一堆就绪线程但没有足够的内核来运行它们,您可以使用定时器在时间片过去时引发中断。

内核堆栈也存储在 VAS 的上半部分。寄存器的保存位置实际上并不重要,这是一个基本的设计决策。 PCB 存储有关分配给某个进程及其对应物理副本的 VAS 部分的信息。 VAS 的其余部分通过切换标志在页表中不存在。如果一个线程试图在那里读、写或执行,内核会杀死它(Linux 上的段错误)。

【讨论】:

    猜你喜欢
    • 2018-07-08
    • 2019-02-17
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    相关资源
    最近更新 更多