前言

Windows的内部实现也近似于“一切皆文件”的思想,当然,这一切都只在内核里才有,下载一个WinObj这软件就可以看到,Windows上各种设备、分区、虚拟对象都是挂载到根“\”下的,通过这个树可以访问各种设备、驱动、文件系统等等。

Windows与Linux不同的就是把这些对象又重新封装了一层WindowsAPI,对外以设备、盘符、文件等等表现出来,重新封装WindowsAPI的目的是为了兼容性,而设备、盘符、文件这些是为了让普通用户更好理解。

所以进程在内核中以数据的形式保存在内存中,也可以看成一个文件。

进程概述

系统分配资源的最小单位!

就是担当分配系统资源(CPU时间、内存等)的基本单位。

cpu分配:一个cpu一个时间片只能执行一个进程,不同cpu内核并行运行这个进程中不同的线程。

虚拟内存分配:一个进程默认可以分配到和物理内存一样大小的虚拟内存。

进程的运行不仅仅需要CPU,还需要很多其他资源,如内存啊,显卡啊,GPS啊,磁盘啊等等,统称为程序的执行环境,也就是程序上下文。

单CPU进行进程调度的时候,需要读取上下文+执行程序+保存上下文,即进程切换。所以进程的创建和销毁都是相对于系统资源,所以是一种比较昂贵的操作。

进程将内存的地址空间划分为:

  • 代码段(文本段 code segment/text segment):保存应用的执行代码。通常是指用来存放程序执行代码的一块内存区域
  • 数据段(data segment):全局变量,常量,静态变量。例如C#。 通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
  • 堆栈段:
    • 堆:存放各种变量数据(new的对象),大小动态调整。
    • 栈:子任务(线程、协程)独立存放数据的地方(函数调用、参数、局部变量等)

进程的虚拟地址空间虽然很大,但是它被划分成了很多分区

详细查看:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/virtual-address-spaces

PCB

进程控制块(Processing Control Block),是操作系统核心中一种数据结构,主要表示进程状态,其作用是使一个程序成为一个能够独立运行的基本单位,并且可以并发执行的进程。
进程是运行中的程序实例,是操作系统程序动态执行的基本单元。为了满足操作系统对进程的控制,例如调度,中断,执行等操作,操作系统将每个进程描述为一个叫做进程控制块(PCB) 的数据结构,在PCB中存储着操作系统对控制一个进程所需要的全部信息,可以根据PCB找到程序代码,找到程序的数据,程序获得的资源等等。所以一个进程对于操作系统来说就是一个PCB。

在windows中执进程控制块是由 EPROCESS 块来表示的。 EPROCESS
块位于内核层之上,它侧重于提供各种管理策略,同时为上层应用程序提供基本的功能接口。所以,在执行体层的进程和线程数据结构中,有些成员直接对应于上层应用程序中所看到的功能实体。

EPROCESS结构属于内核的执行体层,包含了进程的资源相关信息诸如句柄表、虚拟内存、安全、调试、异常、创建信息、I/O转移统计以及进程计时等。

进程生命周期

三状态模型:

  • 阻塞态:等待某个事件的完成(比如等待IO数据)。

  • 就绪态:等待系统分配处理器运行(随时可以运行)。

  • 运行态:占有处理器运行。

  • 一般不太讨论创建态和结束态。5状态和7状态模型很少用到

五状态模型

  如果所有进程都做好了准备,操作系统会从未运行队列中以轮转的方式调度每个进程。但是这里有个问题,如果并非所有进程都做好了准备呢?也许未运行的进程中有些进程正在等待某一事件的发生,也就是处于阻塞,因此单纯的对所有未运行的进程进行轮转是不科学的,应该对所有已经就绪的进程进行调度。解决这种问题的最好方法就是将未执行进程队列拆分为两个队列分别是就绪队列和阻塞队列,由此进程的状态由2状态变为了3状态,此外还要增加新建退出态,这十分有必要。改进后的状态模型如下图所示。

  运行态:进程正在执行。
  就绪态:进程做好了准备,随时接收调度。
  阻塞态:进程在等待某些事件的发生,在事件发生前不能执行,如I/O操作。
  新建态:刚刚新建的进程,操作系统还未将其加载至内存,通常是PCB已经创建但是还并未加载到内存中的新程序。
  退出态:操作系统从可执行进程组中释放的进程。
  新建态与推出态十分有必要。在一个进程被新建时它并非绝对会被调入内存,通常是分两步,首先创建该进程的PCB,并与之关联,但是此时可能面临内存不足或者操作系统限制了最大进程数导致这个进程还无法被调入进程,因此该进程被暂时留在新建态,在这个状态的进程PCB已经创建并且加载进内存,但是进程的代码和数据往往还留在外村中等待加载。
  退出态也和新建态同理。当进程因为某些人原因要被终止时,此时并不直接将其调出内存,首先操作系统会停止执行该进程的代码,但是暂时让其留在内存中,因为某些辅助程序或是支持程序会来记录该进程相关数据和信息,此时进程停留在退出态。等相关程序收集完所需信息后,再将其所有数据从内存中移除。
  关于阻塞,就绪和运行三种状态的转换更为普遍和便于理解。操作系统从就绪队列中调度某个进程进入运行态运行,当时间片结束后操作系统将其放回就绪态执行其他进程,如果在执行期间进程必须等待某些事件,便将其放入阻塞态,然后调度其他进程执行。当该进程等待的事件完成后操作系统则将其放回就绪态等待调度。
  但是此时又有一个问题,如果所有阻塞进程放在同一个阻塞队列中,当一个事件完成后操作系统不得不扫描整个队列找到那些等待该事件的进程然后将其放进就绪队列中,这样的效率十分低下,因此通常是为每一个事件创建一个阻塞队列。同理当按照优先级进行调度时,也会将优先级相同的进程放进一个就绪队列,避免扫描等低效的做法,这是典型的用空间换时间的做法。

七状态模型

  在介绍七状态模型前,我们思考一个问题,三个基本状态(就绪,运行和阻塞)的所有进程都必须存储在内存中,此时就可能出现一种情况,即所有进程都处于阻塞态,没有就绪状态的进程,此时又开始了处理器的空转,处理器没办法执行进程只能开始等待进程从阻塞态恢复就绪态,并且加入此时又有新的进程处于新建态,由于内存不足,处于新建态的进程也没办法进入内存无法执行,这是一个十分致命的处理器空转问题,解决这个问题有两个方法:扩大内存,很显然成本太高了;将阻塞态的进程暂时调出内存放回磁盘,来让新建态的进程有足够内存进入就绪态开始处理器的调度和运行。
  但是在将一个阻塞态进程挂起后,操作系统可以选择接纳一个新建态进程进入就绪队列,也可以选择将一个之前挂起的进程恢复就绪态,并且为了减少操作系统的负载操作系统更倾向于后者。但是处于挂起的进程也可能还并未接触阻塞,将一个阻塞进程放回内存没有任何意义,于是更好的方法是将挂起区分为两个状态即就绪/挂起态阻塞/挂起态,这样每次操作系统就只需要考虑是否应该把进程从就绪/挂起态换回就绪态即可。完整的七状态模型如下:

  阻塞/挂起态:进程在外存中并等待一个事件。
  就绪/挂起态:进程在外存中,但只要载入内存即可开始运行。
  并且操作系统允许进程从就绪变为就绪/挂起态,或从阻塞/挂起态变更为阻塞态,只是这样做的意义不大,因此并不会这样做。
  导致进程被挂起的事件有以下几种:
  1、交换。为了释放内存空间。
  2、其他OS原因。操作系统可能会挂起后台进程或者工具进程,或挂起可能会导致问题的进程。
  3、交互式用户请求。用户希望挂起一个进程来进行调试。
  4、定时。进程可被周期性的执行,并在等待下一个时间间隔时挂起。
  5、父进程请求。父进程可能希望挂起后代进程的执行,以检查或修改挂起的进程。

进程调度算法

抢占式调度

在“抢先式调度”中,大多数任务都分配有其优先级。有时,即使较低优先级的任务仍在运行,在另一个较低优先级的任务之前运行具有较高优先级的任务也很重要。较低优先级的任务会保留一段时间,并在较高优先级的任务完成执行时恢复。

非抢占式调度

在这种调度方法中,已将CPU分配给特定的进程。使CPU保持繁忙的进程将通过切换上下文或终止来释放CPU。这是可用于各种硬件平台的唯一方法。那是因为它不需要抢先式调度之类的特殊硬件(例如计时器)。

详细请看:https://zhuanlan.zhihu.com/p/356089708

  • 先来先服务调度算法
  • 最短作业优先调度算法
  • 高响应比优先调度算法
  • 时间片轮转调度算法
  • 最高优先级调度算法
  • 多级反馈队列调度算法

进程间通信的方式

  1. 管道(pipe)及有名管道(named pipe):管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。

  2. 信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。

  3. 消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限的进程可以按照一定的规则向消息队列中添加新信息;对消息队列有读权限的进程则可以从消息队列中读取信息。

  4. 共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。

  5. 信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间的同步和互斥手段。

  6. 套接字(socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。

进程特征

    • 动态性 进程既然是进程实体的执行过程,因此进程是有一定的生命期。而程序只是一组有序指令的集合,并放在某种介质上,本身无运行的含义,因此程序是个静态的实体。
    • 并发性(concurrence) 

      并行性是指两个或者多个事件在同一时刻发生,这是一个具有微观意义的概念,即在物理上这些事件是同时发生的;而并发性是指两个或者多个事件在同一时间的间隔内发生,它是一个较为宏观的概念。

      在多道程序环境下,并发性是指在一段时间内有多道程序在同时运行,但在单处理机的系统中,每一时刻仅能执行一道程序,故微观上这些程序是在交替执行的。应当指出,通常的程序是静态实体,它们是不能并发执行的。为了使程序能并发执行,系统必须分别为每个程序建立进程。进程,又称任务,简单来说,是指在系统中能独立运行并作为资源分配的基本单位,它是一个活动的实体。多个进程之间可以并发执行和交换信息。一个进程在运行时需要运行时需要一定的资源,如
      cpu,存储空间,及i/o设备等。在操作系统中引入进程的目的是使程序能并发执行。

    • 独立性  这是指进程实体是一个能独立运行的基本单位,同时也是系统种独立获得资源和调度的基本单位。
    • 异步性(asynchronism) 
      在多道程序设计环境下,允许多个进程并发执行,由于资源等因素的限制,通常,进程的执行并非“一气呵成”,而是以“走走停停”的方式运行。内存中每个进程在何时执行,何时暂停,以怎样的方式向前推进,每道程序总共需要多少时间才能完成,都是不可预知的。或者说,进程是以异步的方式运行的。尽管如此,但只要运行环境相同,作业经过多次运行,都会获得完全相同的结果,因此,异步运行方式是允许的。
    • 结构特征 从结构上看,进程实体是由程序段、数据段及进程控制块三部分组成。
      (进程控制块(PCB):进程控制块是进程实体的一部分,它记录了操作系统所需要的、用于描述进程情况及控制进程运行所需的全部信息。os 是根据PCB来对并发执行的进程进行控制和管理的)

多进程

在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态,这便是多任务(多进程)。现代的操作系统几乎都是多进程操作系统,能够同时管理多个进程的运行。 多进程带来的好处是明显的。但是多进程对于系统的资源要求甚高,资源浪费也比较严重。应用多进程场景最多的是windows系统,例如同时打开运行软件,每个软件打开相当于运行一个进程。

进程调度

由于CPU同时刻只能执行一个进程,如果我们不加以控制的话,一个进程可能使用CPU直到运行结束,于是出现了操作系统调度器,而进程也成为了调度单位。

进程上下文

进程的运行不仅仅需要CPU,还需要很多其他资源,如内存啊,显卡啊,GPS啊,磁盘啊等等,统称为程序的执行环境,也就是程序上下文。

进程并发

 在这里就出现了并发的概念,调度器切换CPU给不同进程使用的速度非常快,于是在使用者看来程序是在同时运行,这就是并发,而实际上CPU在同一时刻只在运行一个进程。

单个CPU只有并发,没法并行。

进程同步

1、进程同步的基本概念

多道程序环境下,进程是并发执行的,不同进程间存在着不同的相互制约关系。为了协调进程之间的相互制约关系,达到资源共享和进程协作,避免进程之间的冲突,引入了进程同步的概念。

(1) 临界资源

多个进程可以共享系统中的各种资源,但其中许多资源一次只能为一个进程所使用,我们把一次只允许一个进程使用的资源成为临界资源。

对临界资源的访问,必须互斥的进行。每个进程中,访问临界资源的那段代码成为临界区。

为了保证临界资源的正确使用,可以把临界资源的访问过程分为四个部分。

1) 进入区。为了进入临界区使用临界资源,在进入去要检查可否进入临界区。

2) 临界区。进程中访问临界资源的那段代码。

3) 退出区。将正在访问临界区的标志清除。

4) 剩余区。代码中的其余部分。

do {

entry section;

critical section;

exit section;

remainder section;

}while (true)

(2) 同步

同步已成为直接制约关系,它是为完成某种任务而建立的两个或多个进程。这些进程因为需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系。进程间的直接制约关系就是它们之间的相互合作。

(3) 互斥

互斥亦称间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一个进程才允许去访问此临界资源。

实现临界区互斥的基本方法

在进入区设置和检查一些标志来表名是否有进程在临界区中,如果已有进程在临界区,则在进入区通过循环检查进行等待,进程离开临界区后则在退出区修改标志。

进程和线程之间的区别

  这是十分常见的问题,在此做同一归纳和梳理:
  1、进程是资源分配的基本单位,线程是处理器调度的基本单位。
  2、同一进程内线程共享进程状态和资源,例如数据段,代码段,I/O信息等。但是每个线程内也有独立的数据,每个线程都拥有属于自己的栈,线程属性信息存在线程控制块中,例如上下文数据,线程状态,调度信息等。
  3、线程是轻量级进程,因此创建和销毁所消耗的系统资源更少,更快。
  4、同一进程内线程切换所消耗的资源相比进程切换更少且更快。
  5、同一进程内线程共享大部分数据因此通信起来更加方便,无需借助内核。

最新文章

  1. return array 评论添加状态和提示信息
  2. FDTD Python API
  3. MySQL基础之第7章 索引
  4. Mac OS系统 - 将视频转换成gif
  5. cocoa pods
  6. android studio class org.bouncycastle.asn1.asn1primitive overrides final method equals
  7. Apache HTTP Server mod_session_dbd模块mod_session_dbd.c 安全漏洞
  8. MYSQL 表分区的 3 方法
  9. js实现url链接encode加密
  10. Java基于Socket文件传输示例
  11. [转帖]linux 清空history以及记录原理
  12. TensorFlow从入门到理解(二):你的第一个神经网络
  13. 字符转ASCII码
  14. Vue系列之 => 组件切换
  15. od 转储 二进制文件常用命令
  16. Android-MediaPlayer-音频播放-普通准备
  17. luoguP5068 [Ynoi2015]我回来了
  18. 微信小程序—智能小蜜(基于智能语义解析olami开放平台)
  19. Python全栈 项目(电子词典、协程、pdb调试)
  20. MySQL 主主同步

热门文章

  1. Elasticsearch使用系列-ES简介和环境搭建
  2. Centos 7 安装LAMP以及在Apache上安装positiveSSL。
  3. unixbench服务器性能测试
  4. kubernetes之部署dashboard 和heapster
  5. java解洛谷P1003铺地毯问题
  6. JavaScript数据结构之链表
  7. 【建议收藏】Redis超详细入门教程大杂烩
  8. Java 高效编程(Effective Java)中文第三版(补档)
  9. Spring学习一: Ioc容器
  10. C语言之清空缓存区