浅谈操作系统原理(四) 操作系统中的线程和进程-张柏沛IT博客

正文内容

浅谈操作系统原理(四) 操作系统中的线程和进程

栏目:Linux 发布时间:2020-03-18 14:57 浏览量:255

什么是操作系统

操作系统是管理计算机软件和硬件的程序。
所以本质上,操作系统是一个程序,软件。

具体功能有配置内存,决定资源供需顺序,控制输入输出设备,提供操作界面

高度概括就是:操作系统是管理软硬件,配置资源和供用户交互的软件系统


为什么需要操作系统
因为我们不可能直接操作硬件
因为设备种类繁多,要统一界面


操作系统的基本功能
CPU资源,存储器资源,IO设备资源和文件资源。操作系统同一管理这些计算机资源。例如我们读写文件,不可能直接操作硬盘,而是通过操作系统去硬盘获取。(操作系统同一管理计算机资源)

有了操作系统,我们无需面向CPU,硬盘等硬件进行编程。只需面向操作系统编程即可。(操作系统实现了对计算机资源的抽象)

操作系统提供了用户和计算机之间的交互接口


* 操作系统的相关概念
并发性 **
共享性
虚拟性
异步性

并发性是后面三个概念的基础

并行和并发
并行是多个事件可以在同一时刻发生
并发是多个事件可以在同一时间间隔交替发生

并行和并发在计算机中的体现
对于单核处理器而言,一个核心在同一时刻只能运行一个程序,所以如果单核处理器要运行多个程序,只能对每一个程序设置一小段时间片,让多个程序按照时间片规定时间交替运行,这就是并发(程序A运行时间片内规定的时间,再让程序B运行时间片规定的时间,再让A运行规定时间,如此循环,从而达到单处理器“同时”运行多个程序的效果,但其实CPU不是同一时刻运行多个程序)

对于多核处理器,处理器的一个核在同一时刻还是只能运行一个程序,因此在一个核心中,程序还是并发的。核心与核心之间,程序是并行的。

PS: 一个计算机可以有多个处理器,处理器又分为单核处理器和多核处理器
单核处理器只能并发不能并行处理程序
多核处理器由于有多个核心,所以一个处理器也能并行处理程序
计算机如果有多个单核处理器或者一个多核处理器,都是可以并行执行程序的

4个单核处理器和一个4核的处理器的速度相比,后者更快,因为后者的4个核心是放在一块芯片上的(放在一个CPU上),其数据是共享的,进程通信和交互更快


概括起来就是:
并发是多个程序可以同时运行,但不是同一时刻运行
并行是多个程序同一时刻运行


共享性
共享性表现为操作系统的资源可供并发的多个程序共同使用

共享性可以分为互斥共享形式和同时访问形式
互斥共享就是程序A使用资源时对资源上锁,其他程序无法使用该资源,等到A使用完毕并释放资源程序B才可以使用该资源。
同时访问是某一资源在一段时间内并发的被多个程序访问。即同一时间段内多个程序交替使用某一资源

所以同时访问也不是多个程序能同一时刻使用同一资源

什么时候会是互斥共享,什么时候会是同时访问?
要根据使用的资源而定。例如多个程序使用磁盘就是同时访问,多个程序使用打印器就是互斥共享

虚拟性
虚拟性表现为将一个物理实体转变为若干个逻辑实体
物理实体真实存在,逻辑实体是虚拟的

虚拟的技术有时分复用技术和空分复用技术


时分复用就是不同程序并发使用资源,多道程序分时交替使用计算机的硬件资源。例如,在单处理器中,多个程序会交替执行,交替使用处理器资源。这样可以提高资源利用率。

时分复用技术包括虚拟处理器技术和虚拟设备技术

虚拟处理器技术是:
为每个程序建立进程,多个程序分时复用处理器(交替运行)

虚拟设备技术是:
物理设备虚拟为多个逻辑设备
每个程序占用一个逻辑设备
多个程序通过逻辑设备并发访问这个物理设备


空分复用技术包括虚拟磁盘技术和虚拟内存技术
虚拟磁盘技术就是将一块物理硬盘在逻辑上分成多个逻辑盘(C盘,D盘,E盘),这样其中一个逻辑盘遭到破坏也不会影响到其他逻辑盘

虚拟内存技术,就是程序运行时需要大量内存存储数据,但是有部分数据是不经常使用的,此时这部分数据会放到磁盘而不是内存中。如果需要使用到这部分不经常使用的数据才会将其从磁盘交换到内存中。
虚拟内存技术在逻辑上扩大程序的存储容量,使程序可以使用到比实际内存更多的内存量。

对于虚拟化,可以理解为分身术。

异步性
其实还是指多个进程可以并发执行
进程的执行不是一气呵成的,而是走走停停的形式推进。还是以使用资源为例,某个进程执行到某一步时需要使用某一资源,如果这个资源被其他进程占用,进程就会停止或者等待。此时进程不会一直占用CPU,而是会让出CPU给其他进程使用,即使这个进程的时间片没有使用完。


===========================================

 

进程(Process)

进程是系统进行资源分配和调度的基本单位
进程是程序独立运行的载体

为什么需要进程
在没有操作系统的时代,计算机只能运行完一个程序再运行下一个程序(顺序执行),而资源也只属于当前运行的程序。而当前程序可能只用了资源的一部分,但是由于资源也只属于当前运行的程序,所以其他程序不能使用该资源的其他部分造成资源浪费。
操作系统出现后,就引入了多道程序设计的概念。进程的出现就是为了合理隔离资源提高资源使用效率

这样说吧,有了进程,多个程序才可以共享资源(存储器,CPU等),使得计算机的资源利用率大大提高
为什么说有了进程多个程序就可以共享资源
因为进程是并发的交替执行的,所以进程使用资源时也是交替使用;而没有进程,程序是顺序执行的,一个程序运行完了才轮到下一个程序运行,意味着一个程序对资源使用完毕才能给下一个程序使用,相当于独占资源

 

进程的实体(进程到底长什么样子的
主存中的进程形态
在主存中,进程的形态是一段连续存储的空间(一个字块或多个字块组成的块),这个空间叫做进程控制块(PCB),这个控制块用来记录进程的相关信息。

在这个控制块中,包含以下信息:
标识符:作为一个进程的唯一标记,即pid(进程id)
状态:如,运行状态还是阻塞状态等
程序计数器:指向进程即将执行的下一条指令的地址
内存指针:程序代码,进程数据相关指针
上下文数据:存储着进程执行时,处理器存储的数据(寄存器和高速缓存中的数据)
IO状态信息:记录着被进程IO操作所占用的文件,是一个列表结构
记账信息:记录进程使用处理器的时间,时钟数总和等
还有其他的信息。

PCB是描述和控制进程运行的通用数据结构
PCB使得一个进程成为独立运行的基本单位。
进程被调度具体表现为PCB被操作系统读写
PCB是常驻内存的

高度概括:进程就是内存中的一段连续存储空间(PCB)。PCB记录着进程的所有信息。进程被调度的过程就是PCB被读写的过程。

 

 

线程(Thread)


线程是操作系统进行运行调度的最小单位


线程是包含在进程当中的,是进程中实际运行和工作的单位
一个进程可以并发多个线程,每个线程执行不同的任务。

也就是说一个进程运行其实是该进程的多个线程在交替运行
操作系统运行一个进程其实是运行这个进程中的线程
一个进程要完成的是一个大任务,而一个个线程将这个大任务切割为一个个小任务,每个线程完成一个小任务。 

进程和线程是一对多关系,一个进程至少有一个线程。
进程是一个存储空间是一个仓库,而线程是仓库中的工人

一个进程内的所有线程可以共享进程的资源(可以使互斥共享形式的共享或者同时访问形式的共享)


比较

    进程    线程
资源    资源分配的基本单位    不拥有资源(想要资源得从进程中取)
调度    独立调度的基本单位(调度进程实际是调度进程中的线程)    独立调度的最小单位
开销    开销大(因为要管理线程和分配资源)    开销小(因为同一进程的线程资源是共享的)
通信    进程IPC    通过读写同一进程数据来通信

 

* 进程的5个状态
就绪
阻塞
执行
创建
终止 

 

就绪状态:进程被分到除了CPU资源外的所有必要资源的状态
只要在获取CPU的使用权就可以立刻运行

系统中多个处于就绪状态的进程会排成一个队列,叫做就绪队列。

 

执行状态:就绪队列中的进程获取CPU后,其程序正在执行则称这个进程为执行状态。
单处理器中,某个时刻只能有一个进程处于执行状态。
如果计算机只有一个CPU,该计算机某时刻只有一个进程处于执行状态。

 

阻塞状态:当进程因为某种原因而放弃占用CPU的状态叫阻塞状态。某种原因如:其他设备或资源由于被其他进程占用而未就绪导致无法继续执行

处于阻塞状态的进程会被放入阻塞队列中。


多个并发的进程,同一时刻只有一个进程处于执行状态,其他进程都是就绪状态或阻塞状态。


就绪,执行和阻塞状态的切换:

就绪-执行的切换

就绪进程都放在就绪队列中。
当轮到某进程被系统调度时,该就绪进程会从就绪队列被弹出,被分配时间片,并占用CPU进行程序运行。此时进程变为执行状态
当进程运行完时间片规定的时间后,进程会回到就绪队列中,由执行状态改为就绪状态,CPU被下一个进程使用。

 

执行-阻塞的切换
在进程执行过程中,如果进程发送IO请求遇到阻塞(资源被其他进程锁住)或者执行磁盘IO读写时,(即使这个进程的时间片没用完)该进程也会主动让出CPU给其他进程使用,改执行状态的进程会变成阻塞状态的进程。

 

阻塞-就绪的切换

当IO完成后,阻塞进程会被唤醒变成就绪进程等待CPU的下一次调度。


创建状态:进程创建包括两步:创建PCB和进入就绪队列。
创建进程时拥有PCB但其他资源尚未分配好的状态。
操作系统提供了fork函数让我们可以创建进程。

终止状态:进程归还PCB后的状态。


在这里顺便说一下IO操作和CPU操作:


IO设备根据用途分为3类:

人机交互类外部设备,简称外部设备,如打印机、显示器、鼠标、键盘等。这类设备数据交换速度相对较慢

存储设备,如磁盘,光盘(不包括内存)

网络通信设备,用于和远程设备通信的设备,如网络接口

速度:存储设备>网络通信设备>人机交互外部设备

所以以前的一个重要误区是认为IO设备就是磁盘,其实不只磁盘


根据共享方式不同分为
独占式使用设备,只能以互斥共享的方式共享的IO资源设备,如打印机

分时共享使用设备,能以同时访问的方式共享的IO资源设备,如磁盘

虚拟设备,未知

 

IO操作和CPU操作的关系:
以磁盘为例,每一个磁盘都会安装一个DMA硬件(DMA是一种叫做直接内存访问的技术,该技术使得辅存可以直接读写内存,和内存交换数据而无需CPU的参与)
这个DMA硬件使得磁盘具有DMA技术和功能,而这个DMA硬件就像一个安装在磁盘的"小型CPU"
这个DMA处理器具体功能就是,当一个进程要进行磁盘IO操作的时候,CPU会向磁盘发送IO请求,DMA处理器接受请求后,由DMA处理器负责进行IO操作(也就是从内存读写数据到磁盘,或者从磁盘读写数据到内存),在这个过程中,CPU不会去参与IO操作,而是继续执行其他进程。原因是IO操作很慢,CPU不能一直这样等下去。
当IO操作完成后,DMA硬件通过总线发送一个中断指令给CPU,CPU就会去内存中读取(磁盘写入进内存的)数据,并交由进程使用

也就是说由于IO操作而进入阻塞状态中的进程其实是在等待IO操作完成
而此时CPU是在为其他进程服务,没有参与IO操作
CPU唯一和IO交互的时刻就是发送IO请求和接受IO响应

结论是:IO操作和CPU操作是异步的

 

============================

 

进程同步

生产者消费者模型
有一群生产者进程生产产品,并将这些产品提供给消费者进程进行消费。生产者和消费者可以并发执行,两者之间设置了一个缓冲区池,生产者进程将生产的产品放到一个缓冲区,消费者进程可以从缓冲区取走消费者。

假设有三个生产者进程和三个消费者进程,生产者做的事情是对缓冲区的一个数据k进行+1,而消费者要进行-1

由于缓冲区是在缓存(高速缓存)中,对缓冲区的数据进行修改需要将缓冲区的数据拷贝一份到CPU寄存器操作才行。
所以生产者的操作是
register = k    # 数据拷贝一份到寄存器
register = register+1   # 寄存器内数据+1,这一步是在CPU中执行,左边的register是放在寄存器暂存的
k = register    # 将寄存器的数据覆盖到缓冲区


6个进程(或者线程),共18个操作,这6个进程是并发的,这会导致上面的18个操作会同时(同一时间间隔)发生而导致混乱

例如 
            register    k
生产者进程1   10       10     register=k(将缓存读取到进程1中的寄存器)
生产者进程1   11       10     register=register+1
消费者进程2   10       10     register=k(将缓存读取到进程2中的寄存器,缓存中的k还是10,因为进程1还未将register写入缓冲区中)

消费者进程2   9       10     register=register-1 
消费者进程2   9       9      k=register  (进程2的register写入缓存)
生产者进程1   11        11   k=register(进程1register写入k)

按理说 进程1对k+1,进程2对k-1,结果k还是10,最后k是11(脏读)

原因是这多个进程是并发执行,却没有互相通信,最后导致缓冲区的数据混乱。


哲学家进餐问题


情景如下:五个哲学家,其生活方式是交替的进行思考(就绪状态)和进餐(执行状态),他们共坐在一个圆桌上,有5个碗和五根筷子。平时哲学家思考,饥饿就会进餐。
进餐时,一个哲学家会先拿他左边的筷子,再拿它右边的筷子。只有拿到左右两根筷子才会进餐。如果只拿到左边的筷子,但右边的筷子被别的哲学家拿了,就只有等待右边的筷子被释放这个哲学家才能进餐(阻塞状态)。

有个极端情况:
如果5个哲学家都饿了,同时拿起了左边的筷子,想拿右边的筷子时发现右边的筷子都被拿走了。
此时5个哲学家都会等待,一直等一直等,最后5个哲学家都饿死了。(死锁)

筷子就是资源,哲学家就是进程。


上面生产者消费者模型和哲学家进餐问题出现的原因是:
1.进程是并发执行的
2.彼此间没有通信

进程间的同步作用就是对竞争资源在多进程间的使用进行次序协调。使并发执行的多个进程之间可以有效的使用资源和合作。

在上面的生产者消费者模型和哲学家进餐中,主存和“筷子”都是临界资源。
临界资源指:一些虽作为共享资源却无法同一时刻被多个进程或线程共同访问的资源。
当进程或线程在使用临界资源时,其他进程必须依据操作系统的同步机制等待占用进程释放该共享资源才可以重新竞争使用共享资源。

高度概括:临界资源是一种共享资源(可以被互斥共享或同时访问的形式共享),却无法被多个进程或线程同一时刻访问。


进程同步原则
空闲让进:若资源没有被占用,操作系统会允许某进程使用这个资源
忙则等待:资源有占用,请求进程要等待
有限等待:虽然资源被占用,但是资源不能一直被一个进程占用导致其他进程一直等待。该原则保证某进程是有限时间的等待就能使用资源
让权等待:进程等待时需要让出CPU(执行状态变为阻塞状态)


进程间同步的方法:
1.消息队列
2.共同存储
3.信号量


线程间同步
我们知道,多个线程在进程中也是每个线程分配时间片交替执行,共享资源的。
当多线程并发使用进程资源,也同样会发生上面的生产者消费者问题和哲学家进食问题,所以同一个进程中的线程间也需要同步。

线程同步的方法:
1.互斥量
2.读写锁
3.自旋锁
4.条件变量

 

具体这些方法的实现在下一节给出

 

=================================

Linux进程管理


Linux进程相关概念

在Linux中,进程分为三种类型:
前台进程是具有终端,可以和用户交互的进程。前台进程会占用整个终端(就是shell命令行界面)

后台进程是没有占用终端的进程。
后台程序基本不和用户交互,优先级比前台进程低
在执行的命令后面加一个&就可以变成一个后台进程

后台进程无法通过ctrl+c结束,可以通过kill结束

守护进程(daemon)是特殊的后台进程,他会一直运行直到系统关闭。
进程名字以“d”结尾的一般都是守护进程,如mysqld,httpd,crond,sshd
守护进程也可以通过kill结束


进程ID
进程ID是进程的唯一ID,表现为非负整数,最大的pid由操作系统决定。

进程的父子关系
一个进程可以通过操作系统的fork函数创建一个子进程。
父子进程关系可以通过pstree命令查看

pid为0的进程为idle进程,是系统创建的第一个进程
pid为1的进程为init进程,是0号进程的子进程,用于完成系统初始化
init进程是所有用户进程的祖先进程。所有的初代用户进程都是由init进程产生的。


进程的状态标记
R 处于运行的状态
S 睡眠状态
D 等待IO的睡眠状态
T 暂停状态
Z 正在退出状态或僵尸进程


操作进程的命令
ps
ps -aux --sort=-pmem    # 按使用内存排序
ps -aux --sort=-pcpu    # 按使用cpu排序

top
kill/pkill


要始终记住一件事:进程在阻塞或者等待的时候是会让出CPU的,不会一直占用CPU的

 

PS:如果系统对一个进程创建多个子进程,他会为每个子进程拷贝一份主进程的数据,资源和(内存)空间,并且每个进程间的资源和空间是独立的互不干扰的。所以进程间数据不共享。
而一个进程创建多个线程,这些线程共用一个进程的数据和资源。所以多线程间,数据和资源是共享的(共享一个进程的)

体现为: A进程有变量x
如果A创建了a,b,c线程,线程a,b,c共享变量x,线程a对x修改,再在b中查看x是看到的改变后的x
如果A创建了A1,A2两个子进程,那么系统会多开出两块空间和资源分给这两个进程,所以A1,A2也会有属于自己的x。A,A1和A2三个进程各自有一个x变量,A改变自己的x不会影响A1的x。

因为创建一个子进程,系统会复制一份和父进程一样大的空间和资源,而创建线程不用系统新分配资源,所以多进程的开销大于多线程


===================================

 

作业管理之进程调度

进程调度是指:计算机通过决策算法决定哪个就绪进程可以获得CPU的使用权

进程调度有两步:
1是保留旧进程的运行信息,请出旧进程
2是选择新进程,准备运行环境并分配CPU

进程调度的机制:
1.就绪队列的排队机制
为了方便进程调度,会创建一个就绪队列放就绪进程

2.选择运行进程的委派机制
系统会根据算法策略从就绪队列选出进程来分配CPU资源并执行

3.新老进程的上下文切换机制
进程从执行状态变为就绪状态时,系统会保存该进程在CPU的环境(上下文),上下文会从CPU的高速缓存保存到主存中;进程从就绪状态变为执行状态会将上次保存的上下文信息载入,体现为上下文从主存载入到CPU高速缓存中。


非抢占式调度:处理器一旦分配给某个进程,该进程一直使用处理器不让出。直到进程完成工作或者由于IO阻塞才会让出CPU
抢占式的调度:允许调度程序以一定的策略暂停当前运行的进程,保存好旧进程的上下文,分配处理器给新进程。这也是我们常说的多进程根据时间片交替运行的方式。

对比
    抢占式    非抢占式
开销    频繁切换,开销大    切换少,开销少
公平性    相对公平    不公平
应用    通用系统    专用系统

抢占式调度可以让多个进程交替使用CPU资源,相对公平
非抢占式调度会让不在执行的进程一直使用不到CPU,不公平


进程调度算法
1.先来先服务算法
先进入就绪队列的进程先运行

2.短进程优先调度算法
调度程序优先选择就绪队列中估计运行时间最短的进程
该算法不利于长作业进程的运行

3.高优先权优先调度算法
每一个进程都有其优先级,调度进程优先选择权重的进程运行
该算法可以使紧迫的任务可以优先执行
前台进程的优先级高于后台进程

4.时间片轮转调度算法
按照先来先服务的原则排列好就绪进程
每次从队列头部取出待执行进程,分配一个时间片执行,执行完时间片规定的时间就会让出CPU,并将该进程插入队列尾部等待下一次调度
该算法是最公平的调度算法,但是不能保证及时响应用户

 

 

作业管理之死锁


死锁是指,两个或以上的进程在执行过程中由于竞争资源或者彼此通信问题造成的阻塞现象,若无外力作用,两个进程都无法进行下去。

死锁产生的原因:竞争资源(资源不足),进程调度顺序不当

例如有两个进程A,B
A已经占用了打印机资源,但是他还需要获取传真机资源
B已经占用了传真机资源,但是他还需要获取打印机资源

A和B各自等待对方将自己所需的资源释放出来,但是等待过程中A和B都不释放自己所占用的资源。

如果此时系统中多一个传真机或者打印机,死锁就不会发生
或者A先申请获取打印机再申请传真机,完了之后再让B申请传真机再申请打印机,按照这个顺序调度也不会发生死锁

死锁产生的4个条件
互斥条件
进程对资源的使用是排他性的,资源同一时刻无法被多个进程同时使用

请求保持条件
进程至少保持一个资源有提出新资源的请求,新资源被占用请求被阻塞,被阻塞的进程不释放自己占用的资源

不可剥夺条件
资源在使用完毕之前,其他进程不能抢夺该资源

环路等待条件
发生死锁时,必然存在进程-资源环形链

只需破坏4个条件中后三个条件中的任意一个就能防止死锁。


银行家算法也可以防止死锁。

 

具体的作者也没有怎么整明白,所以不细说

 

如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > 浅谈操作系统原理(四) 操作系统中的线程和进程

热门推荐
推荐新闻