【OSTEP】多道程序和时分共享 | 虚拟地址空间 | 用户栈vs内核栈 | 进程结构: struct thread | 虚拟vs物理地址空间 | 地址转换方案

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介: 【OSTEP】多道程序和时分共享 | 虚拟地址空间 | 用户栈vs内核栈 | 进程结构: struct thread | 虚拟vs物理地址空间 | 地址转换方案

💭 写在前面:

本系列博客为复习操作系统导论的笔记,内容主要参考自:

  • Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau, Operating Systems: Three Easy PiecesA. Silberschatz, P. Galvin, and G. Gagne,
  • Operating System Concepts, 9th Edition, John Wiley & Sons, Inc., 2014, ISBN 978-1-118-09375-7.Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .



0x00  早期操作系统(OS in The Early System)

Load only one process in memory.(只在内存中运行一个进程)

  • Poor utilization and efficiency (利用率低,效率差)

0x01  多道程序和时分共享(Multi-programming and Multi-tasking)

Multi-programming(多道程序)

  • Load multiple processes in memory.
  • Execute one for a short while and switch processes between them in memory.
  • Increase utilization and efficiency.

Time-sharing (multitasking)(时分共享)

Logical extension in which CPU switches jobs so frequently that users can interact with each job while it is running, creating interactive computing.

Cause an important protection issue(保护问题)

  • Errant memory accesses from other processes. (来自其他进程的错误内存访问)
  • 多个程序同时驻留在内存中,保护就成了重要问题。人们不希望一个进程可以读取其他进程的内存,更别说修改了。

0x02  进程地址空间(Process Address Space)

OS creates an abstraction of physical memory. (OS创造一个物理内存抽象

Contains all about a running process.  (包罗所有正在运行的进程)

Consists of program code, heap, stack, etc. (由程序代码、堆、栈组成)

  • Code : Where instructions live.
  • Heap : Dynamically allocate memory.
  • Stack : Store return addresses or values; Contain local variables and arguments to routines

(为了便于讲解,我们假设只有这三个部分)

0x03  虚拟地址空间(Virtual Address Space)

都是假象!凉凉月色为你思念成河,化作春泥呵护着我……

Every address in a running program is virtual. (程序运行时你看到的所有地址都是虚拟的)

  • OS translates the virtual address to physical address

例子:下面是一个打印内存地址的简单程序:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
  printf("location of code : %p\n", (void*)main);
  printf("location of heap : %p\n", (void*)malloc(1));
  int x = 3;
  printf("location of stack : %p\n", (void*)&x);
  return x;
}

🚩 运行结果如下:(在64位Linux环境下跑的)

💡 由此可见:代码在地址空间开头,然后是堆,而栈在这个大型虚拟地址空间的另一端。所有的这些地址都是虚拟的,是假的!纯纯的 fake!都是特喵的骗人的!并且将由操作系统和硬件翻译成物理地址,以便从真实的地理位置获取该地址的值。

0x04  内核是个什么玩意(What About Kernel)

Each OS process has its own virtual address space and part of each virtual address space is reserved for the kernel.

(每个操作系统都有自己的虚拟地址空间,并且每个虚拟地址都是要留一部分空间给内核的)

  • The size is configurable (e.g., 1G out of 4G).

When a process traps into the kernel, kernel uses the mapped space reserved for the kernel. (当一个进程陷阱进入内核时,内核使用为保留给内核的映射空间)

Although the kernel uses virtual address mapping, most of the kernel memory is mapped linearly onto physical addresses

(尽管内核使用内存地址映射,但 绝大多数内核的内存还是以线性地方式映射到物理地址上的

0x05  用户栈 VS 内核栈(User Stack vs Kernel Stack)

In general, two types of stacks are used to run application programs.(一般来说,有两种类型的栈被用来运行应用程序):

  • When they run in user mode, the user stack is used. (当它们在用户模式下运行时,使用的是用户栈)
  • When they run in kernel mode (via system call), the kernel stack is used. (当它们在内核模式下运行时 (通过系统调用),使用的是内核栈)

When application programs invoke a system call(当应用程序调用一个系统调用时):

  • Enters the kernel via trap (interrupt).  (通过陷阱(中断)进入内核
  • Switch from user stack to kernel stack. (从用户栈切换到内核栈
  • In Pintos, kernel stack is allocated 4KB away from the start of PCB (Limited – do not allocate big static variables inside functions).

Raise the privilege level(提高权限级别)

0x06  进程结构: struct thread(Process Structure)

💬 代码:pintos/src/threads/thread.h

struct thread
{
  /* Owned by thread.c. */
  tid_t tid;                       /* Thread identifier. */
  enum thread_status status;       /* Thread state. */
  char name[16];                   /* Name (for debugging purposes). */
  uint8_t* stack;                  /* Saved (kernel) stack pointer. */
  int priority;                    /* Priority. */
  struct list_elem allelem;        /* List element for all threads list. */
    /* Shared between thread.c and synch.c. */
  struct list_elem elem;           /* List element. */
#ifdef USERPROG
/* Owned by userprog/process.c. */
  uint32_t* pagedir; /* Page directory. */
#endif
/* Owned by thread.c. */
  unsigned magic;                  /* Detects stack overflow. */
};

🔍 status:

0x07  逻辑(虚拟)VS 物理地址空间(Logical (Virtual) vs. Physical Address Space)

The user program deals withlogical (virtual) addresses, it never sees the real physical addresses.   用户程序处理的是 逻辑(虚拟)地址,它永远不会看到真正的物理地址

  • Logical address(逻辑地址):由 CPU 生成,也被称为虚拟地址。
  • Physical address(物理地址):内存单元看到的地址。

The concept of a logical address space that is bound to a separate physical address space (i.e., mapping between logical address space and physical address space) is central to proper memory virtualization.  绑定到独立物理地址空间的逻辑地址空间 (即逻辑地址空间和物理地址空间之间的映射) 的概念是正确的内存虚拟化的核心

The run-time mapping from virtual to physical addresses is done by a hardware device called the memory management unit (MMU) .

从虚拟地址到物理地址的运行时映射是由一个称为内存管理单元(MMU)的硬件设备完成的。

0x08  虚拟内存与物理内存之间的映射: 简单概述(Mapping Between Virtual to Physical Memory: Simple Overview)

  • Divide logical (virtual) memory into blocks of same size called pages (size is power of 2, between 512 bytes and 8192 bytes) .   将逻辑(虚拟)内存分为相同大小的块,称为页(大小是2的幂,在512字节和8192字节之间)。
  • Divide physical memory into fixed-sized blocks called frames.  将物理内存划分为固定大小的块,称为 frames。
  • Page and frame size are usually the same.  页和帧的大小通常是一样的。  
  • Keep track of all free frames.  追踪所有空闲的框架。
  • To run a program of size n pages, we need to find m free frames (m can be smaller than n; partially load -> virtual memory). 为了运行一个 页大小的程序,我们需要找到 个空闲的帧( 可以比 小,部分加载 → 虚拟内存)。
  • Each process sets up a page table to translate logical to physical addresses.  每个进程都设置了一个页表,将逻辑地址转换为物理地址。

0x09  地址转换方案: 简单概述(Address Translation Scheme: Simple Overview)

由CPU产生的地址被分为:

  • Page number (p) – used as an index into a page table which contains base address of each page in physical memory.
  • Page offset (d) – combined with base address to define the physical memory address that is sent to the memory unit.

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.10.4
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau, Operating Systems: Three Easy Pieces

A. Silberschatz, P. Galvin, and G. Gagne,

Operating System Concepts, 9th Edition, John Wiley & Sons, Inc., 2014, ISBN 978-1-118-09375-7.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
24天前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
65 4
|
25天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
29天前
|
算法 调度
探索操作系统的心脏:内核与进程管理
【10月更文挑战第25天】在数字世界的复杂迷宫中,操作系统扮演着关键角色,如同人体中的心脏,维持着整个系统的生命力。本文将深入浅出地剖析操作系统的核心组件——内核,以及它如何通过进程管理来协调资源的分配和使用。我们将从内核的概念出发,探讨它在操作系统中的地位和作用,进而深入了解进程管理的机制,包括进程调度、状态转换和同步。此外,文章还将展示一些简单的代码示例,帮助读者更好地理解这些抽象概念。让我们一起跟随这篇文章,揭开操作系统神秘的面纱,理解它如何支撑起我们日常的数字生活。
|
3月前
|
算法 调度 Python
探索操作系统的内核——一个简单的进程调度示例
【9月更文挑战第17天】在这篇文章中,我们将深入探讨操作系统的核心组件之一——进程调度。通过一个简化版的代码示例,我们将了解进程调度的基本概念、目的和实现方式。无论你是初学者还是有一定基础的学习者,这篇文章都将帮助你更好地理解操作系统中进程调度的原理和实践。
|
4月前
|
调度 虚拟化 容器
探索操作系统的心脏:内核与进程管理
【8月更文挑战第28天】在数字世界的复杂迷宫中,操作系统扮演着关键角色。它如同一座桥梁,连接硬件与软件,确保一切顺畅运行。本文将深入剖析操作系统的核心——内核和进程管理,揭示它们如何协同工作,保障系统的稳定与高效。通过简化的比喻,我们将一探究竟,了解操作系统背后的神秘面纱。
|
4月前
|
算法 安全 调度
揭秘操作系统的心脏:内核与进程管理
【8月更文挑战第27天】在数字世界的庞大机器中,操作系统扮演着至关重要的角色。本文将深入探讨操作系统的核心组件之一——内核,以及它是如何高效地管理和调度进程的。通过浅显易懂的语言和生动的比喻,我们将一起探索这一技术领域的奥秘,并了解其对整个计算生态的影响。无论你是技术新手还是资深爱好者,这篇文章都将为你打开一扇了解操作系统深层工作机制的大门。
|
3月前
crash —— 查看进程的内核栈的内容
crash —— 查看进程的内核栈的内容
|
5月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
5月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
182 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
4月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。