进程是计算机操作系统中非常重要的概念。是一种非常重要的抽象。
====================================================
一、为什么要引入进程这个概念?
先从计算机的体系结构——冯诺依曼体系结构。它是一种将程序指令存储器和数据存储器合并在一起的存储器结构。程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置,因此程序指令和数据的宽度相同。这个体系结构有三大原则:采用二进制逻辑、程序存储执行和计算机由五大部分组成。这五大部分是:运算器、存储器、控制器、输入设备、输出设备。
冯诺依曼计算机体系结构理论要点:
(1)采用存储程序方式,指令和数据不加区别混合存储在同一个存储器中,指令和数据都可以送到运算器进行运算,即由指令组成的程序是可以修改的;
(2)存储器是按地址访问的线性编址的一维结构,每个单元的位数是固定的;
(3)指令由操作码和地址组成。操作码指明本指令的操作类型,地址码指明操作数和地址。操作数本身无数据类型的标志,它的数据类型由操作码确定;
(4)通过执行指令直接发出控制信号控制计算机的操作。指令在存储器中按其执行顺序存放,由指令计数器指明要执行的指令所在的单元地址。指令计数器只有一个,一般按顺序递增,但执行顺序可按运算结果或当时的外界条件而改变;
(5)以运算器为度中心,I/O设备与存储器间的数据传送都要经过运算器;
(6)数据以二进制表示。
这种结构特点是“程序存储,共享数据,顺序执行”,需要 CPU 从存储器取出指令和数据进行相应的计算。
这种操作系统有以下几个特点:
所有的应用程序以进程的方式运行在比操作系统权限更低的级别。
每个进程都有自己独立的地址空间;使得进程之间的地址空间相互隔离。
CPU由操作系统进行统一分配,每个进程根据优先级都有机会得到CPU。具体来讲就是进程的调度方面的知识;
总体目标是使得每个进程从逻辑上看来都可以独占计算机的资源。
另外也使得CPU能在多个进程之间很好地共享。
====================================================
三、进程的描述
既然有了进程这个概念来描述运行中的程序。那么操作系统也必须具备一些手段来管理进程。
操作系统的作用当然不仅仅要管理进程,还要管理计算机中个其他资源:内存、设备(I/O)、文件等;
操作系统控制和管理系统资源;操作系统是管理系统资源的实体。
为处理器执行进程而进行调度和分派,给进程分配资源,响应用户程序的基本服务请求。
操作系统为了控制进程和管理资源需要哪些信息?
操作系统管理这些资源和进程的普遍方式就是:创造一个表。构造并维护它所管理的每个实体的信息表。
一个普遍的方法是操作系统构造并维护它所管理的每个实体的信息表。
操作系统一般维护着4中不同类型的表:内存、I/O、文件和进程。(操作系统控制表)
内存表:内存表用于跟踪内存和虚拟内存(外存)。//内存模型和虚拟外存后续文章再介绍。
内存表用于跟踪内(实)存、外存(虚拟内存);
内存的某些部分为操作系统而保留,剩余部分是进程可以使用的。
保存在外存中的进程使用某种类型的虚拟内存或简单的交换机制。
所以内存表应该包括:
内存或虚拟内存块的任何保护属性;管理虚拟内存所需要的任何信息;
I/O表:
这个表用于管理计算机中系统中的I/O设备和通道。
操作系统需要知道I/O操作的状态和作为I/O传送的源和目的内存单元。
文件表:
提供关于文件是否存在、文件在外存中的位置、当前状态和其他属性的信息。
大部分信息是由文件管理系统维护和使用的。
进程表:
内存、I/O、文件是代表进程而被管理,因此进程表中必须有对于这些资源的直接或间接引用。
这些表自身也必须可以被操作系统看到,因此它们受制于内存管理。
操作系统最初是如何创建表?
很显然需要有一些基本环境的信息。这是一个配置问题。
当操作系统初始化后,它必须可以使用定义基本环境的某些配置数据,这些数据必须在操作系统之外,
通过人的帮助或一些自动配置软件产生。
参考链接:
进程的组成和描述:https://blog.csdn.net/zpznba/article/details/88399361
我们使用进程映像描述一个进程:程序、数据、栈、属性(进程控制块)的集合;
其实进程就简单分成三个部分(程序、数据、进程控制块)
进程控制块存放在系统内存中。是进程存在的唯一标识,是操作系统感知进程存在的重要数据结构。
PCB保存了很多关于进程相关的信息。如下:
标识符 (就是进程的ID,身份证)
状态 (运行、就绪、阻塞等)
优先级 (决定进程调度)
程序计数器 (存放下一条指令所在单元的地址的地方,告知CPU下一条指令所在的内存地址)
内存指针
上下文数据 (处理机现场信息,方便恢复现场)
I/O状态信息
记账信息
进程控制块(PCB):由操作系统创建和管理、是操作系统能够支持多进程和多处理的关键工具。
当进程被中断后,操作系统会把程序计数器和处理器寄存器(上下文数据)保存到进程控制块中的相应位置。
进程状态也被改变为其他的值,例如阻塞态或者就绪态。
关于进程控制块的组织形式,这里也有很多内容。暂时不展开讨论;
====================================================
四、进程的控制
要对进行进程控制就必须在操作系统中有专门的结构,进行进程创建、终止、进程通信和资源管理。
这样的结构被称为:内核(kernel)。
内核的本身不是进程,是硬件的延伸,内核是通过各种原语操作来完成各种控制和管理功能的。
原语可以认为是机器指令的延伸。由若干条机器指令构成,用以完成特定功能的一段程序。为了保证操作的正确性,原语在执行期间是不可分割的。
用于进程控制的原语有:创建进程、撤销进程、阻塞进程、唤醒进程、调度进程、改变优先级;
这里又联系到进程的优先级,我们来讲讲优先级排列的一些原则:
1、根据进程的类型:系统进程优先级比用户进程优先级高;
2、进程所使用的资源量:占用CPU时间越多,优先级越低;
3、进程在系统中等待时间:等待时间越长,优先级越高;
等等....
====================================================
五、进程的行为模型
两状态模型:未运行、运行;
未运行的进程必须保持在某种类型的队列中。
因为存在着一些处于非运行状态但已经就绪等待执行的进程,
而同时存在另外一些处于阻塞状态等待I/O操作结束的进程。
所以分派器还得考虑队列中那些未被阻塞且在队列中时间最长的进程。
可以将非运行状态分成两种:阻塞(等待I/O操作完成)和就绪;
三状态模型:运行、阻塞、就绪;
新建态、退出态对于进程管理是非常有用的。
五状态模型:新建态、就绪态、阻塞/等待态、运行态、退出态;
创建进程分两步:执行一些必要的辅助工作(新建态)、执行进程;
退出进程分两步:终止进程使进程转换到退出态(保留数据方便其他程序读取)、然后真正退出进程;
当处于新建态,程序保留在外存中,没有放到内存里。
交换活动的需要:
I/O的活动比计算速度慢很多。所以会产生所有的进程都在等待I/O的情况。这个时候处理器就处于空闲的状态,且内存都满了,没有空间给新的进程了。
一种解决方法是交换。把内存中某个进程的一部分或全部移动到磁盘中。
挂起队列就是指这些被换出到磁盘的进程组成的队列。
交换 是一个 I/O操作。但是由于磁盘I/O一般是系统中最快的I/O,所以交换也能提高性能。
-->因此进程模型中又要增加一个状态,叫做挂起态。因此内存中释放的内存可以被调入的另一个进程使用。
当操作系统已经执行了一个换出操作,它有两种选择(将一个进程取到内存中):
一、接纳一个新创建的进程(这样做会增加负载总数);
二、调入一个以前被挂起的进程(倾向于这个);
所以就绪态、阻塞态就变成了4个:就绪态、阻塞态、阻塞/挂起态、就绪/挂起态;
挂起进程的原因:
交换:一方面是提供更多的内存空间,这样可以调入一个就绪/挂起态进程、或者增加分配给其他就绪态进程的内存;
其他OS原因:
挂起后台进程或工具程序进程,或者被怀疑导致问题的进程
交互式用户请求
定时
父进程请求
====================================================
六、进程的调度
参考链接:进程的调度方式和调度算法总结:https://blog.csdn.net/vqtyh/article/details/78282555
了解了进程如何被控制,进程的行为模型后,就开始考虑进程的调度问题,也就是如何协调多个进程使用CPU的问题。
简单看下参考链接的内容,就可以了解这部分内容。
====================================================
七、进程间的通信(IPC)
多个进程之间存在信息交换的需求。
可以分为低级通信(数据量小)、高级通信(数据量大);
低级:信号量(互斥量(互斥锁)是特殊的信号量,临界区);PV操作是低级通信方式;
高级:见下方;
高级通信方式:
一、共享存储 ->信号量通常和共享内存结合在一起,信号量用来同步对共享内存的访问;
二、消息队列
三、管道通信
分为管道和FIFO。
四、客户机-服务器系统(CS)
1)套接字
同一台电脑上多个应用程序之间的通信(进程间通信):解决多对进程同时通信时端口以及物理线路的多路复用问题;
计算机网络+UNIX操作系统广泛使用——>称为最流行的网络通信程序接口 //这种通信的传输效率低,开销大,用于跨网络进程的交互多。属于I/O通信。不只在内存中玩,效率自然就低了。
2)远程过程调用和远程方法调用
进程的同步与互斥-->其实也属于进程的通信范畴
临界资源的互斥访问,实现资源共享;
信号量机制:整型信号量(表示资源的数量)、记录型信号量、
四种进程或线程同步及互斥的控制方法;
信号量
互斥量
临界区 ->前三个都可以归为信号量这个范畴;
事件 ->这个实际上是通过管道通信机制实现的;
此外从另一个角度可以总结进程间通信的方式有五种:
进程间的五种通信方式:https://www.cnblogs.com/zgq0/p/8780893.html
1.管道:速度慢,容量有限,只有父子进程能通讯 ;它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。 //存在于内存中的文件,不属于任何文件系统,由内核管理。
2.FIFO:任何进程间都能通讯,但速度慢。也称为命名管道,它是一种文件类型。 FIFO是Linux基础文件类型中的一种。但,FIFO文件在磁盘上没有数据块,仅仅用来标识内核中一条通道。各进程可以打开这个文件进行read/write,实际上是在读写内核通道,这样就实现了进程间通信。
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。独立于进程而存在的,在系统内存中,有内核管理的。
1、2、3本质上是很接近,从某个角度看都是一种模式。传统的管道队列模式采用内存缓冲区的方式,数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程,读写存在于内核缓存区的文件。
4.信号量:不能传递复杂消息,只能用来同步 //和第五种结合使用,用于互斥和同步
5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中。如果一个进程更新了段中的数据,其他进程也立即会看到更新。由一个进程创建的段,也可以由另一个进程读写。每个进程都把它自己对共享内存的映像放入自己的地址空间。
====================================================
八、死锁问题
死锁的4个必要条件:https://www.cnblogs.com/bopo/p/9228834.html
是指各并发进程彼此互相等待对方所拥有的资源。
这些并发进程在得到对方的资源之前并不会释放自己所拥有的资源。
从而造成大家都想得到资源而又都得不到资源,各并发进程不能继续向前推进的状态。
产生死锁的4个必要条件:
1、互斥条件
2、请求和保持条件
3、不剥夺条件
4、循环等待条件
产生死锁的原因:
1、系统资源不足;
2、进程推进顺序非法;
死锁如何解决?
互斥锁:
信号量用于多线程同步,一个线程完成率某一个动作就通过信号告诉别的线程,别的线程再进行某些动作。
互斥锁是用于多线程互斥,一个线程占用了某一个资源,那么别的资源就无法访问,直到这个线程离开,其他线程才可以利用这个资源。
也就是说互斥锁已经备某线程加锁,如果此线程再去加锁则无效,也就是说互斥锁只能加锁一次。
临界区:
保证某一时刻只能有一个线程能访问数据的简便方法,
在任意时刻只允许一个线程对共享资源进行访问。
如果有多个线程试图同事访问临界区,那么在有一个线程进入后其他所有试图访问次临界区的线程将被挂起,并一直持续到进入临界区的线程离开。
====================================================
九、继续讨论信号量
用于解决线程之间的同步
多个并发的进程彼此之间围绕着紧俏的资源产生了两种关系:同步或互斥;
信号量正是解决资源竞争的最有效途径。
举例:
信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一。当该整数值为零时,所有试图通过它的线程都将处于等待状态。
信号量定义两种操作:Wait(等待)和Release(释放);
这是一个原子操作;
当一个线程调用Wait操作时,它要么得到资源然后将信号量减一,要么一直等下去(指备放入阻塞队列),直到信号量大于等于一时。
Release实际上是在信号量上执行加操作。对应于车辆离开停车场,该操作之所以叫释放,是因为释放了信号量守护的资源。
信号量守护资源。解决线程之间调用资源而产生的竞争关系。
信号量的操作是原子操作;
信号量分为两种:计数信号量、二进制信号量;
二进制信号量,又称为互斥锁。
V操作:增加信号量的数值;signal操作, 释放信号量;
P操作(pending):减少数值;:wait操作,sleep操作,获取信号量;
对信号量的访问具有原子性;
====================================================
相关链接:
进程详解(1):https://www.cnblogs.com/jacklu/p/5317406.html
进程与线程:https://www.cnblogs.com/qianqiannian/p/7010909.html
进程间通信FIFO:https://blog.csdn.net/qq1113231395/article/details/88824916
详解linux进程间通信-消息队列: https://www.cnblogs.com/liudw-0215/p/8978945.html