[OS]Three Easy Pieces Chapter 4

The Abstraction: The Process

进程的定义,简单来说,就是运行的程序。

主要的挑战

即使我们只有几个实际的物理CPU,操作系统如何提供一个有无限CPU的假象。

操作系统通过虚拟化来提供这种假象。为了实现这种虚拟化,我们需要:

  • 低级硬件支持:上下文切换
  • 高级策略:调度策略(根据历史信息、工作负载、性能指标等)

1 The Abstraction: A Process

操作系统对运行中程序的抽象,称之为进程。进程只是一个运行中的程序;在任何时间,我们都可以通过盘点进程在执行过程中访问或影响的系统的不同部分来概括进程

在任何时候,一个进程都可以通过以下状态来描述:

  • 内存空间中的内容
  • 寄存器中的值
  • 交互的IO设备

2 Process API

抽象的来看,任何操作系统至少要提供一下API

  • Create

  • Destroy

  • Wait

  • Miscel Control

    例如,OS希望可以暂停某个进程的执行,之后再继续执行它

  • Status

    获取进程的一些状态信息

3 Process Creation: A Little More Detail

为了执行一个程序,操作系统:

  • 首先,将硬盘中的程序(指令、静态数据等)装载进内存中。

    硬盘中的程序必须符合某种可执行格式。早期的操作系统装载时将整个程序装载进内存,现代操作系统通常采用懒装载,即,只将需要的内容装载到内存中。

  • 之后,操作系统需要分配栈内存,并用参数初始化这个栈(argc,argv)

  • 分配堆内存

  • 处理IO相关的初始化

    Unix中,每个进程初始有三个打开的文件描述符(标准输入,标准输出,标准错误)

  • 最后,操作系统跳转到新进程的entry point(main())开始执行。

4 Process States

进程三状态模型

5 Data Structures

操作系统需要记录所有就绪进程,运行进程,阻塞进程,并且能够正确的转换进程的状态。比如,当某个IO事件完成了,需要将任何等待该事件的进程从阻塞队列移动到就绪队列中。

在xv6内核中,操作系统需要跟踪并记录如下内容。当一个进程将要进行上下文切换的时候,将其寄存器的值保存到 context 结构体中,之后将下一个要调度的进程的 context 结构体中的值装载到实际的寄存器中,完成上下文切换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Saved registers for kernel context switches.
struct context {
uint64 ra;
uint64 sp;

// callee-saved
uint64 s0;
uint64 s1;
uint64 s2;
uint64 s3;
uint64 s4;
uint64 s5;
uint64 s6;
uint64 s7;
uint64 s8;
uint64 s9;
uint64 s10;
uint64 s11;
};

enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };

// Per-process state
struct proc {
struct spinlock lock;

// p->lock must be held when using these:
enum procstate state; // Process state
void *chan; // If non-zero, sleeping on chan
int killed; // If non-zero, have been killed
int xstate; // Exit status to be returned to parent's wait
int pid; // Process ID

// wait_lock must be held when using this:
struct proc *parent; // Parent process

// these are private to the process, so p->lock need not be held.
uint64 kstack; // Virtual address of kernel stack
uint64 sz; // Size of process memory (bytes)
pagetable_t pagetable; // User page table
struct trapframe *trapframe; // data page for trampoline.S
struct usyscall *usyscall; // shared data between kernel and user
struct context context; // swtch() here to run process
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
};

[OS]Three Easy Pieces Chapter 4
https://erlsrnby04.github.io/2024/10/18/OS-Three-Easy-Pieces-Chapter-4/
作者
ErlsrnBy04
发布于
2024年10月18日
许可协议