操作系统之虚拟化之进程

抽象:进程

如何运行多个程序

虚拟化计

如果我们的硬件只含有一个cpu,但是我们想要让用户同时运行多个程序,我们就要让用户以为我们有多个cpu。下面举个例子。
假设我们开设了一个加工厂,但是我们为了多赚钱,多拉生意。我们就同时承接了裤子加工,帽子加工,衣服加工。我们需要让那些老板认为我们的工厂就是为他们生产的,实际上我们是轮流生产的(即cpu轮流给应用程序使用),我们需要有一个机制来安排什么时候生产不同的加工品(这个就是进程调度机制)。如果有时候老板要来看(用户用到了这个软件),我们就需要马上停止当前产品的生产,切换到这个老板说需要的产品(进程切换),但是停止当前的产品生产我们需要把当前的产品放好(保存进程上下文),等以后需要生产的时候再拿出来用(时间片再次轮到该进程使用),同时需要把该老板的产品需要的生产环境给布置起来(加载新的进程的上下文进行运行),这个回耗费我们的一定时间,减少我们的生产效率(所以要尽量减少进程切换,这会白白耗费cpu资源)。

如何进行虚拟化

资源的可划分方式

时分共享(time sharing)是操作系统共享资源所使用的最基本的技术之一。通过允许资源由一个实体使用一小段时间,然后由另一个实体使用一小段时间,如此下去,所谓的资源(例如,CPU 或网络链接)可以被许多人共享。时分共享的自然对应技术是空分共享,资源在空间上被划分给希望使用它的人。
例如,磁盘空间自然是一个空分共享资源,因为一旦将块分配给文件,在用户删除文件之前,不可能将它分配给其他文件。

资源的调度策略

解决资源如何进行分配,程序如何进行运行的问题。
操作系统中有一些智能以策略(policy)的形式存在。策略是在操作 系统内做出某种决定的算法。例如,给定一组可能的程序要在 CPU 上运行,操作系统应该 运行哪个程序?操作系统中的调度策略(scheduling policy)会做出这样的决定,可能利用历史信息(例如,哪个程序在最后一分钟运行得更多?)、工作负载知识(例如,运行什么 类型的程序?)以及性能指标 (例如,系统是否针对交互式性能或吞吐量进行优化?)来做出决定。

进程

什么是进程

运行中的程序就是进程,什么是程序,程序就是磁盘上的二进制文件。
要理解进程,我们首先需要理解机器态是什么。
机器态:程序可以在运行的时候读取或者更新内容。

机器态的组成部分

内存:将磁盘上的二进制文件加载到内存中,即程序读取和写入的程序都在内存中。
寄存器:程序计数器 (Program Counter,PC)(有时称为指令指针,Instruction Pointer 或 IP)告诉我们程序当前 正在执行哪个指令;类似地,栈指针(stack pointer)和相关的帧指针(frame pointer)用于管理函数参数栈、局部变量和返回地址。

分离策略与机制

在许多操作系统中,一个通用的设计范式是将高级策略与其低级机制分开[L+75]。你可以将机制看成为系统的“如何(how)”问题提供答案。例如,操作系统如何执行上下文切换?策略为“哪个(which)” 问题提供答案。例如,操作系统现在应该运行哪个进程?将两者分开可以轻松地改变策略,而不必重新考虑机制,因此这是一种模块化(modularity)的形式,一种通用的软件设计原则。

进程的API

我们平时开发,后台的功能无非就是增删改查,其他事情无非就是如何让增删改查如何更加高效,更加安全。进程也是如此。
**创建(create):**操作系统必须包含一些创建新进程的方法。在 shell 中键入命令或双击应用程序图标时,会调用操作系统来创建新进程,运行指定的程序。
**销毁(destroy):**由于存在创建进程的接口,因此系统还提供了一个强制销毁进程的接口。当然,很多进程会在运行完成后自行退出。但是,如果它们不退出,用户可能希望终止它们,因此停止失控进程的接口非常有用。
**等待(wait):**有时等待进程停止运行是有用的,因此经常提供某种等待接口。
**其他控制(miscellaneous control):**除了杀死或等待进程外,有时还可能有其他控制。例如,大多数操作系统提供某种方法来暂停进程(停止运行一段时间),然后恢复(继续运行)。
**状态(statu):**通常也有一些接口可以获得有关进程的状态信息,例如运行了多长时间,或者处于什么状态

进程的创建

问:进程是如何创建的,程序是如何变成一个进程的。

加载代码与静态数据到内存中

操作系统运行程序必须做的第一件事是将代码和所有静态数据(例如初始化变量)加载(load)到内存中,加载到进程的地址空间中。程序最初以某种可执行格式驻留在磁盘上
(disk,或者在某些现代系统中,在基于闪存的 SSD 上)。因此,将程序和静态数据加载到内存中的过程,需要操作系统从磁盘读取这些字节,并将它们放在内存中的某处(见图 4.1)。
![image.png](https://img-blog.csdnimg.cn/img_convert/ccb22875cfafdbb95b2f888233a354dd.png#clientId=u5cff60a5-53f6-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=499&id=uf7fb11bb&margin=[object Object]&name=image.png&originHeight=499&originWidth=565&originalType=binary&ratio=1&rotation=0&showTitle=false&size=37552&status=done&style=none&taskId=u13289973-4aef-40be-8941-61552f12dea&title=&width=565)

在早期的(或简单的)操作系统中,加载过程尽早(eagerly)完成,即在运行程序之
前全部完成。现代操作系统惰性(lazily)执行该过程,即仅在程序执行期间需要加载的代 码或数据片段,才会加载。要真正理解代码和数据的惰性加载是如何工作的,必须更多地 了解分页和交换的机制,这是我们将来讨论内存虚拟化时要涉及的主题。现在,只要记住在运行任何程序之前,操作系统显然必须做一些工作,才能将重要的程序字节从磁盘读入内存。

为程序运行栈分配内存

将代码和静态数据加载到内存后,操作系统在运行此进程之前还需要执行其他一些操作。必须为程序的运行时栈(run-time stack 或 stack)分配一些内存。你可能已经知道,C程序使用栈存放局部变量、函数参数和返回地址。操作系统分配这些内存,并提供给进程。操作系统也可能会用参数初始化栈。具体来说,它会将参数填入 main()函数,即 argc 和 argv数组。
操作系统也可能为程序的堆(heap)分配一些内存。在 C 程序中,堆用于显式请求的动态分配数据。程序通过调用 malloc()来请求这样的空间,并通过调用 free()来明确地释放 它。数据结构(如链表、散列表、树和其他有趣的数据结构)需要堆。起初堆会很小。随着程序运行,通过 malloc()库 API 请求更多内存,操作系统可能会参与分配更多内存给进程,以满足这些调用。
操作系统还将执行一些其他初始化任务,特别是与输入/输出(I/O)相关的任务。例如, 在 UNIX 系统中,默认情况下每个进程都有 3 个打开的文件描述符(file descriptor),用于标准输入、输出和错误。这些描述符让程序轻松读取来自终端的输入以及打印输出到屏幕。在本书的第 3 部分关于持久性(persistence)的知识中,我们将详细了解 I/O、文件描述符等。
通过将代码和静态数据加载到内存中,通过创建和初始化栈以及执行与 I/O 设置相关的 其他工作,OS 现在(终于)为程序执行搭好了舞台。然后它有最后一项任务:启动程序,在入口处运行,即 main()。通过跳转到 main()例程(第 5 章讨论的专门机制),OS 将 CPU的控制权转移到新创建的进程中,从而程序开始执行

进程的状态

进程无非就是三个状态:运行(得到cpu时间片),就绪(得到时间片就可以运行),阻塞(等待发生其他事件的时候运行)。
种状态之一。

  • 运行(running):在运行状态下,进程正在处理器上运行。这意味着它正在执行指令。
  • 就绪(ready):在就绪状态下,进程已准备好运行,但由于某种原因,操作系统选择不在此时运行。
  • 阻塞(blocked):在阻塞状态下,一个进程执行了某种操作,直到发生其他事件时才会准备运行。一个常见的例子是,当进程向磁盘发起 I/O 请求时,它会被阻塞,因此其他进程可以使用处理器。

如果将这些状态映射到一个图上,会得到图 4.2。如图 4.2 所示,可以根据操作系统的载量,让进程在就绪状态和运行状态之间转换。从就绪到运行意味着该进程已经被调度(scheduled)。从运行转移到就绪意味着该进程已经取消调度(descheduled)。一旦进程被阻塞(例如,通过发起 I/O 操作),OS 将保持进程的这种状态,直到发生某种事件(例如,I/O 完成)。此时,进程再次转入就绪状态(也可能立即再次运行,如果操作系统这样决定)。
![image.png](https://img-blog.csdnimg.cn/img_convert/23746bf5708e49965966b90ac2fe6a07.png#clientId=u5cff60a5-53f6-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=279&id=u3e5ab273&margin=[object Object]&name=image.png&originHeight=279&originWidth=334&originalType=binary&ratio=1&rotation=0&showTitle=false&size=22220&status=done&style=none&taskId=uc476b9e4-f761-46b1-9a6b-6e5ee9ccd30&title=&width=334)

数据结构

操作系统是一个程序,和其他程序一样,它有一些关键的数据结构来跟踪各种相关的信息。例如,为了跟踪每个进程的状态,操作系统可能会为所有就绪的进程保留某种进程
列表(process list),以及跟踪当前正在运行的进程的一些附加信息。操作系统还必须以某种方式跟踪被阻塞的进程。当 I/O 事件完成时,操作系统应确保唤醒正确的进程,让它准备好再次运行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值