Linux教程

操作系统-进程

本文主要是介绍操作系统-进程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

进程综述

定义

进程是正在执行程序的实例,包括程序计数器、寄存器和变量的当前值。

进程不只是程序代码,程序代码称为文本段(代码段),还包括当前活动,通过程序计数器的值和处理器寄存器的内容来表示。此外,进程还包括进程堆栈段(临时数据、函数参数、局部变量、地址)和数据段(包括全全局变量。还可能包括堆(heap),是在进程运行期间动态分配内存。

image-20210908001654122

程序和进程的关系:

  1. 程序是被动实体,进程是活动实体(进程有开始,有结束、程序没有;进程会走走停停,程序走停无意义)
  2. 一个程序可以对应多个进程(不同进程间代码段相同,而数据段、堆栈等不同)

为什么要有进程这个概念

核心目的:虚拟化CPU,从而支持多个进程在少量的物理CPU上运行(每个进程以为它独享一个CPU)。

操作系统通过虚拟化(virtualizing)CPU 来提供这种假象。通过让一个进程只运行一个时间片,然后切换到其他进程,操作系统提供了存在多个虚拟 CPU 的假象。这就是时分共享(time sharing)CPU 技术,允许用户如愿运行多个并发进程。潜在的开销就是性能损失, 因为如果 CPU 必须共享,每个进程的运行就会慢一点(上下文切换)。

进程创建

核心问题:程序是如何转化为进程的?(即:操作系统如何启动并运 行一个程序?进程创建实际如何进行?)

  1. 将代码和所有静态数据(例如初始化变量)加载(load)到内存中,加载到进程的地址空间中。
  2. 为程序的运行时栈(run-time stack 或 stack)分配一些内存。
  3. 为程序的堆(heap)分配一些内存。
  4. 执行一些其他初始化任务,特别是与输入/输出(I/O)相关的任务。(在 UNIX 系统中,默认情况下每个进程都有标准输入stdin,标准输出stdout,标准错误stderr三个文件描述符)
  5. 启动程序, 在入口处运行,即 main()。
image-20210907223526668

进程状态

在三状态模型中,进程的三个状态如下:

  • 运行(running):在运行状态下,进程正在处理器上运行。这意味着它正在执行指令。
  • 就绪(ready):在就绪状态下,进程已准备好运行,但由于某种原因,操作系统选择不在此时运行。
  • 阻塞(blocked):在阻塞状态下,一个进程执行了某种操作,直到发生其他事件时才会准备运行。

若加上新建态、退出态,则是五状态模型,两者本质上是一样的,三状态模型更能体现进程核心的状态。

三状态之间的转换如下图:

image-20210907232848968

对应到操作系统中位以下图,处理器中运行的为运行态进程、就绪队列中为就绪态进程、阻塞队列中为阻塞态进程。

需要注意的是,运行态进程有三种转换去向:

  1. 发生I/O事件,进入阻塞队列,若I/O事件完成该进程则可转入就绪队列。
  2. 时间片到期,操作系统则抢占之,使之进入就绪队列,等待下一次调度。
  3. 进程完成,释放。
image-20210907233018507

若考虑到I/O速度较慢且内存数量有限,只能容纳一部分的进程,因此存在内存中所有的进程都在等待I/O的情况。在这种情况中,CPU多数时间处于空闲状态。因此,将所有进程放入内存中是不理智的。可以通过将一部分进程换出到磁盘中,增大操作系统中的进程数目,从而充分利用CPU。

挂起(suspend),即将内存中某个进程的一部分或全部移到磁盘。当内存中不存在就绪态进程时,操作系统就把被阻塞的进程换出到磁盘中的挂起队列(suspend queue),即临时从内存中“踢出”的进程队列。

包含单挂的模型如下,相比与三/五状态模型,增加了一个挂起态:

image-20210908000310613

单挂模型有个缺点:所有已被挂起进程都是阻塞态,那么将被阻塞的进程取回内存无任何意义。若I/O事件完成,阻塞态进程将不再阻塞,可以进入就绪态继续执行。因此可以将挂起态中的进程进行细分,即阻塞/挂起态及就绪/挂起态。

image-20210908000902320

该模型中比较重要的状态转换为:

阻塞/挂起态->就绪/挂起态:若I/O事件完成,则将进程从阻塞/挂起态切换到就绪/挂起态。

进程描述

进程在操作系统内用进程控制块(process control block, PCB)来表示,PCB包含了进程状态、程序计数器、cpu寄存器、cpu调度信息、内存管理信息、记账信息、I/O状态信息等信息。

  • 进程状态: 状态可包括新的,就绪,运行,等待,终止等。
  • 程序计数器 : 计数器表示进程要执行的下个指令的地址。
  • CPU寄存器: 与程序计数器一起,这些寄存器的状态信息在出现中断时也需要保存,以便进程以后能正确的执行。
  • CPU调度信息:这类信息包括进程优先级、调度队列指针和其他调度参数。
  • 内存管理信息:根据内存系统,这类信息包括基址和界限寄存器的值,页表或段表。
  • 记账信息:这类信息包括CPU时间、实际使用时间、时间界限、记账数据、作业或进程数量等。
  • I/O状态信息:这类信息包含分配给进程的I/O设备列表、打开的文件列表等。

进程之间的切换就用到PCB:

image-20210908001914265

xv6中的进程描述信息如下:context即寄存器的上下文。

// 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
}; 

reference

[1] 操作系统-精髓与设计原理

[2] 操作系统导论(ostep)

[3] 操作系统概念

[4] 现代操作系统

这篇关于操作系统-进程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!