操作系统笔记
程序员文章站
2022-07-14 22:19:24
...
进程
4.1 进程是一种抽象
正在运行的程序称为进程。
4.2 进程的API
- 创建:操作系统创建一个新的进程
- 毁灭:操作系统强行杀死一个进程
- 等待:等待一个进程停止运行
- 杂项控制:其它的一些操作,如挂起进程
- 状态:获取进程的状态,如已运行的时间
4.3 创建进程:一些细节
- 从磁盘中加载代码和静态数据到内存中。
- 现代操作系统大多使用懒加载。即需要时才将代码和数据加载进内存。与之相关的技术为分页和交换。
- 分配程序的运行时栈。
- 分配程序的堆。
- 操作系统还会做一些其它的初始化工作,特别是和I/O相关的。如UNIX系统会给每个进程提供三个打开文件描述符,用于标准输入、输出、错误。
- 从程序入口点main()开启程序,OS将CPU的控制权转移给新创建的进程,程序开始它的执行。
4.4 进程状态
- 运行:进程正在处理器上运行,意味着它在执行指令。
- 就绪:进程已经准备好可以运行了,但操作系统并没有运行它。
-
阻塞:进程已执行某种操作,直到发生其他事件才能运行。例如执行I/O操作,直到I/O完成后才能继续执行。
让我们看一个例子,说明两个进程如何在其中某些状态下转换。
首先,假设有两个正在运行的进程,每个进程仅使用CPU(它们没有I / O)。
在这种情况下,每个进程的状态跟踪可能看起来像这样。
在下一个示例中,第一个进程在运行一段时间后发出I / O。此时,该进程被阻塞,从而使另一个进程有运行的机会。
请注意,即使在这样一个简单的示例中,操作系统也必须做出许多决定。首先,在进程0发出I / O操作时,系统必须决定运行进程1。这样做可以通过保持CPU繁忙来提高资源利用率。其次,系统决定在I / O完成时不切换回进程0。目前尚不清楚这是否是一个好的决定。这是由调度算法决定的。
4.5 数据结构
操作系统是一个程序,与任何程序一样,它具有一些关键数据结构,这些数据结构可跟踪各种相关信息。
例如,要跟踪每个进程的状态,操作系统可能会为所有准备就绪的进程保留某种进程list,并提供一些其他信息来跟踪当前正在运行的进程。操作系统还必须以某种方式跟踪阻塞的进程。当I / O事件完成时,操作系统应确保唤醒正确的进程并准备使其再次运行。
下面的代码显示了OS需要跟踪xv6内核中的每个进程的信息类型。
// the registers xv6 will save and restore
// to stop and subsequently restart a process
struct context {
int eip;
int esp;
int ebx;
int ecx;
int edx;
int esi;
int edi;
int ebp;
};
// the different states a process can be in
enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
// the information xv6 tracks about each process
// including its register context and state
struct proc {
char *mem; // Start of process memory
uint sz; // Size of process memory
char *kstack; // Bottom of kernel stack for this process
enum proc_state state; // Process state
int pid; // Process ID
struct proc *parent; // Parent process
void *chan; // If non-zero, sleeping on chan
int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
struct context context; // Switch here to run process
struct trapframe *tf; // Trap frame for the current interrupt
};
上一篇: ROS下编译报错