操作系统基础概念

基本概念

操作系统(Operating System,简称OS)是管理系统资源、控制程序执行、改善人机界面、提供各种服务、合理组织计算机工作流程和为用户有效使用计算机提供良好运行环境的一种系统软件。

操作系统的主要功能是资源管理运行程序,OS直接安装在硬件上,屏蔽硬件细节,向上提供统一抽象接口。

  • 运行程序:编译链接形成可执行文件→外存→内存分配空间→加上PCB控制块形成进程→执行程序→回收内存等软硬件资源

  • 资源包括硬件与软件资源,硬件资源包括CPU、内存、外存、输入输出设备等。资源管理包括处理器管理(进程/线程)、存储管理(内存)、设备管理(I/O)、文件管理、网络与通信管理等

操作系统的资源管理技术主要包括:

  • 资源复用:指多个进程共享物理资源,包括分割资源为较多更小单位的空分复用和分时轮流使用资源的时分复用。进程是有资格获得系统资源的独立主体。
  • 资源虚化:指利用一类事物模拟另外一类事物,造成另外一类事物数量更多或容量更大的假象。如虚拟内存映射。
  • 资源抽象:指利用软件封装复杂的硬件或软件设施,简化资源应用接口的一种资源管理技术。

操作系统的主要目标为:

  • 方便用户使用:尽量屏蔽硬件细节,向上提供统一抽象接口
  • 扩充机器功能:在固有硬件的基础上安装使用各种各样的软件,提供多种服务
  • 管理系统资源:帮助管理各种软硬件资源
  • 提高系统效率:OS可自我管理
  • 构筑开放环境:平台移植性与各操作系统间的互联互操作性

操作系统特性:

  • 并发性(Concurrence):指两个或两个以上的事件或活动在同一时间间隔内发生。(对应的,并行性(parallelism)是指两个或两个以上的事件或活动在同一时刻发生。)。操作系统的并发性是指计算机系统中同时存在若干个运行着的程序,这些程序交替、穿插地执行。
  • 共享性:指操作系统中的资源可被多个并发执行的进程共同使用,而不是被其中某一个程序所独占。
  • 异步性:是并发性的表现特征,在多道程序环境中,程序的执行不是一贯到底,而是“走走停停”,何时“走”,何时“停”是不可预知的。并发执行与顺序执行效果一致
  • 虚拟性:是操作系统资源管理技术的特性,虚拟资源管理技术即资源虚化,将物理上的一个实体变成逻辑上的多个对应物,或把物理上的多个实体变成逻辑上的一个对应物。

单道程序设计与多道程序设计

涉及到操作系统的发展历史,在打卡片的年代里,程序运行时的很多步骤都手动处理,单道程序即一次只执行一个程序,多道程序设计则是指允许多个程序同时进入一个计算机系统的主存储器并启动进行交替计算的方法(并行性,如在CPU运转的时候另一个程序的输入也可同时进行)CPU利用率=(CPU运转时间/同一时间所处理的所有程序的总运行时间)

内核:OS在硬件上的首层抽象,屏蔽硬件细节,向上提供统一抽象接口

系统调用:内核中函数,获取操作系统服务的唯一途径

系统调用过程:请求系统调用→由用户态转换为核心态→发生中断,现场保护→执行完毕,内核(系统)调用返回

系统调用与过程(函数)调用的区别

(1)调用形式不同
过程(函数)使用一般调用指令,其转向地址包含在跳转语句中;系统调用不包含处理程序入口,仅仅提供功能号,按功能号调用。
(2)被调用代码的位置不同
在过程(函数)调用中,调用程序和被调用代码在同一程序内,经过连接编译后作为目标代码的一部分。当过程(函数)升级或修改时,必须重新编译连接。
系统调用的处理代码在调用程序之外(在操作系统中),系统调用处理代码升级或修改时,与调用程序无关。
(3)提供方式不同
过程(函数)由编译系统提供或用户编写,不同编译系统提供的过程(函数)可以不同;
系统调用由操作系统提供,一旦操作系统设计好,系统调用的功能、种类与数量就固定不变了。
(4)调用的实现不同
程序使用一般机器指令(跳转指令)来调用过程(函数),是在用户态运行的;
程序执行系统调用,是通过中断机构来实现的,需要从用户态转变到核心态,在管理态执行。

操作接口:是操作系统为用户提供的操作控制计算机工作和提供服务手段的集合。包括图形用户界面,命令行工具等

OS结构

  • 单体式结构:整个OS为一个大型可执行二进制文件,在内核中以单一程序方式运行

  • 层次式结构:将OS划分为内核与多个模块,垂直排列,为单向调用关系,低层为高层提供服务

  • 客户机/服务器与微内核结构:划分功能模块与微内核,功能模块为服务器进程,用户进程为客户机进程,使用消息传递进行通信,用户进程向服务器进程请求资源,内核管理服务器进程

OS运行模型

  • 非进程模式:将OS组织成一个例行程序,用户程序/数据/堆栈+内核程序/数据/堆栈构成进程映像,操作系统本身不是一个进程,在其上的软件运行时访问内核,加上内核程序构成进程映像进行执行
  • 进程模式:将OS组织成一组系统进程,OS功能由这些系统进程集合提供

处理器管理

处理器

处理器属于分时复用型的共享资源,其中的寄存器被操作系统和各个进程所共享,任意瞬时的寄存器内容构成处理器工作现场。当进程或任务发生切换时,寄存器内容必须被保存,以便进程或任务恢复执行时,还原处理器工作现场。

指令分特权指令与非特权指令:特权指令仅提供给操作系统核心程序使用

处理器状态转换

  1. 用户态转向管态:执行系统调用,请求操作系统服务;中断事件产生,运行程序被中断,操作系统接管处理器,中断处理程序开始工作。
  2. 管态转向用户态:执行加载程序状态字LPSW(Load PSW)指令时转换。

PSW即程序状态字,处理器的工作状态记录在程序状态字(PSW)寄存器中;每个正在执行的程序都有一个与其执行相关的PSW(进程与一个PSW对应);每个处理器都设置一个程序状态字寄存器。

PSW存储的主要信息包括:

  • 程序基本状态:程序计数器、处理器状态位、条件码等

  • 中断码:记录发生的中断事件

  • 中断屏蔽位:决定是否响应中断事件

中断

中断:指程序执行过程中发生某个事件时,终止CPU当前程序,转而执行事件的过程

中断是改变指令执行流程、实现操作系统并发多任务功能的重要硬件机构,也是操作系统实现计算机控制的重要途径。检测中断的方法为:在每两条指令或某些特殊指令执行期间,每当一条指令执行结束时都检测是否发生中断以此来检测并响应中断。

中断源是引起中断的事件,中断装置是发现中断源并产生中断的硬件,当中断事件发生后,它能改变处理器内操作执行的顺序。

分类

  • 强迫性中断:外部随机事件引起,如电源故障,设备出错等
  • 自愿性中断:程序自己引发的期待事件
  • 外中断:处理器与主存之外的中断,如时钟中断、I/O中断等
  • 内中断:处理器与主存内部的中断,如地址越界,算术操作溢出等,内中断不能屏蔽
  • 硬中断:由硬件设施产生的中断信号;硬中断发生时会立刻响应
  • 软中断:利用软件模拟产生的中断信号,用于实现内核与进程或进程与进程之间的通信;接收软中断的进程运行时才能响应

中断与异常的区别

(1)中断不是现行程序引发的,而是由与现行指令无关的中断信号触发的;异常是现行程序引发的
(2)中断处理程序提供的服务一般不是现行程序需要的,通常两条机器指令之间才可响应中断;异常是由程序本身产生的,异常处理一般是现行程序所需要的

中断处理

使用硬件+软件实现中断处理,中断寄存器存储中断字,中断字每一位代表一个中断事件,每条指令执行完毕后检查中断字。中断指令刺激中断源产生中断信号,中断信号置中断字对应位为1,检查中断字发现中断,CPU响应中断请求,中断位置0

发现中断源,响应中断请求→保护现场→启动中断处理程序→中断返回

中断处理程序主要用于处理事件与恢复现场,当响应中断时调用中断处理程序,然后保护现场,不同的中断源对应不同的中断处理程序,维护一个中断处理程序入口的向量表

问题1:在系统中只有一个进程运行时,该进程会不间断地运行吗?

不一定,只要发生了系统调用仍然会产生中断,同时程序运行过程中会产生各种各应的中断信号,如I/O中断,时钟中断或各种内中断,一般来说一个进程运行时不会不间断的运行,总会产生某些中断。

问题2:在系统中没有任何进程运行时,操作系统在干什么?系统会静止吗?

不会,此时会有时钟中断处理程序在运行,等待服务程序的到来;中断犹如计算机系统的心脏,无论何时不能停止跳动,否则,计算机系统将失去驱动力;中断也像刹车,可以使用户程序及系统程序适时停止运行,以便重新分配系统资源,尤其是处理器资源,避免某些程序过长时间地垄断系统资源,破坏系统资源使用的公平性。
进程

进程是一个可并发执行的具有独立功能的程序关于某个数据集合的一次执行过程,也是操作系统进行资源分配和保护的基本单位。

进程与程序的区别

(1)程序是静态的,进程是动态的,进程是按照程序运行的过程。
(2)同一个程序在一段时间内可以同时存在多个执行活动(即进程)分别对不同的数据进行处理

进程的属性

  • 结构性:进程包含了数据集合与运行于其上的程序,至少包含三个部分:程序块、数据块、进程控制快。进程=程序代码+相关数据+PCB
  • 共享性:同一程序运行于不同数据集合上构成不同的进程
  • 动态性:进程的内容(主要是数据)是动态的,随着指令的执行而变化;程序的内容是固定的。
  • 独立性:进程是系统中资源分配和保护的基本单位,也是系统调度的独立单位。
  • 制约性:并发进程之间存在同步、互斥关系;同步:存在协作关系的一个进程在某些执行点需要等待另一个进程发来的同步信号;互斥:共享某些资源的进程需要依次排队使用这些资源。
  • 并发性:在单处理器系统环境下,各个进程轮流占用处理器,即交替、穿插使用处理器。

进程状态

划分进程状态对于简洁、条理地分类管理进程、合理调度系统资源非常必要。

  1. 三态模型

进程至少包含程序代码与数据集两个部分,即包括一系列顺序指令与该指令集合要操作的数据

要让OS管理进程,则必须还加上进程控制块(PCB),进程状态

  • 运行态:占用CPU,执行指令
  • 就绪态:具备运行条件,等待OS调度分配CPU以进入运行态
  • 等待态:进程等待事件发生,目前不能继续执行,缺乏条件
  1. 五态模型
  • 新建态:进程刚被创建,尚未提交参加处理器竞争
  • 运行态:占用CPU,执行指令
  • 就绪态:具备运行条件,等待OS调度分配CPU以进入运行态
  • 等待态:进程等待事件发生,目前不能继续执行,缺乏条件
  • 终止态:进程已经终止,但是进程尚未退出主存
  1. 七态模型

在三态模型中,进程的运行、就绪、阻塞都由OS在内存中进行调度管理,随着进程数的不断增加,系统资源会被瓜分干净,为了平滑系统负荷,必须把某些进程挂起换到磁盘镜像中,因此引入挂起态:

  • 挂起就绪态:进程就绪但位于外存
  • 挂起等待态:进程阻塞并位于外存

OS控制结构:操作系统的控制结构是控制进程、管理系统资源的数据结构,同样类型的数据结构组成表,称为控制表。

  • 进程控制表:登记进程管理信息,控制管理所有进程映像
  • 存储控制表:管理主存与外存
  • I/O控制表:管理I/O设备与通道
  • 文件控制表:登记打开文件的状态、属性信息

进程实体/进程映像

进程实体包括程序块、数据块、进程控制快(PCB)、核心栈

进程控制块PCB:进程创建时建立进程控制块,进程撤销时回收进程控制块,进程控制块与进程一一对应。主要包括标志信息(唯一标识一个进程)、现场信息(让出CPU时当下的CPU现场,便于后来恢复)、控制信息(用于管理和调度进程,如调度信息,资源清单等)等。

核心栈主要记录进程运行在核心态下时跟踪过程调用和过程间参数传递信息

进程实体的内容随着进程的执行不断发生变化,某时刻进程实体的内容及其状态集合称为进程映像。

进程上下文

进程物理实体和支持进程运行的环境合称为进程上下文。进程物理实体主要包括PCB、程序块、数据块等,进程运行环境主要包括核心栈、用户栈、寄存器等

进程队列

处于同一状态的所有PCB链接在一起的数据结构称为进程队列。队列可以按照进程状态进行细分,如就绪队列、等待队列等,通过管理该队列控制进程调度

进程切换

进程切换即中断一个进程的执行转而执行另一个进程。保存被中断进程上下文到其进程控制块中,然后装入新进程上下文,使其从上次断点恢复执行,或者调度一个新的进程。

进程调度的时机

(1)当进程进入等待态时:一个进程陷入阻塞,调一个就绪态的进程来执行
(2)当进程完成其系统调用返回用户态,但不是最有资格获得CPU时:把处理器分配给最有资格获得它的进程,进程切换由此发生。
(3)当内核完成中断处理,进程返回用户态但不是最有资格获得CPU时:发生强迫性中断时的处理情况,同(2)
(4)当进程执行结束时:回收资源,调度处理其他进程

进程的调度依赖于中断,中断是激活操作系统的唯一方法,只有中断发生时操作系统才能接管处理器,才有可能发生进程上下文的切换

进程切换的步骤(假设P1被中断,调度P2开始执行):

中断、保存P1现场信息→修改P1的PCB,将运行态改为等待态或就绪态→将P1加入相关进程队列(等待队列或者就绪队列)→在就绪队列中选择一个进程来执行,如P2→修改P2的PCB,将状态改为运行态→运行P2,直接执行或恢复上次断点状态继续执行

进程切换包含两次模式切换:一个进程的用户态→管态;管态→另一个进程的用户态

进程的控制与管理

OS对进程的控制与管理通过原语来实现

**原语是在管态下执行、完成系统特定功能的不可中断的过程,具有原子操作性。**原语可以采用屏蔽中断的系统调用来实现

(1)进程的创建:

①在主进程表中增加一项,并从PCB池中取一个空白PCB,为新进程分配唯一的进程标识符

②为新进程的进程映像分配地址空间,装入程序和数据。

③为新进程分配内存空间外的其它资源

④初始化进程控制块,如进程标识符、处理器初始状态、进程优先级等

⑤把进程状态置为就绪态并加入就绪进程队列

⑥通知操作系统的某些模块,如记账程序、性能监控程序

(2)进程的阻塞:

进程阻塞是指一个进程让出处理器,去等待一个事件。

①停止进程执行,保存现场信息到PCB

②修改PCB的有关内容,如进程状态由运行改为等待,并把修改状态后的PCB加入相应等待队列

③转入进程调度程序调度其他进程运行

(3)进程的唤醒:

①从相应等待队列中移出进程

②修改进程PCB有关信息,如进程状态改为就绪并把修改PCB后的进程加入就绪队列

③若被唤醒进程优先级高于当前运行进程,则重新设置调度标志

(4)进程的撤销:

①根据撤销进程标识号,从相应队列找到它的PCB

②将该进程拥有的资源归还给父进程或操作系统

③若该进程拥有子进程,则先撤销它的所有子孙进程,以防它们脱离控制

④撤销进程出队,将它的PCB归还到PCB池

(5)进程的挂起和激活:

挂起时:检查要被挂起进程的状态,若处于活动就绪态就修改为挂起就绪态,若处于阻塞态,则修改为挂起阻塞态。被挂起进程PCB的非常驻部分要交换到磁盘对换区。

激活时:把进程PCB非常驻部分调进内存,修改它的状态,挂起等待态改为等待态,挂起就绪态改为就绪态,加入相应队列中。

挂起原语既可由进程自己也可由其他进程调用,但激活原语只能由其它进程调用。

线程

线程:运行在同一个进程中的各个并发任务称为该进程的线程。线程是处理器调度的基本单位

线程实体

线程控制块TCB:包含唯一标识符、状态信息、线程上下文等

私有存储区:包含局部变量,用户栈等

核心栈:线程在核心态工作下存放的函数调用传递的参数、返回地址等信息

线程状态

只有三个关键状态:运行、就绪、等待(阻塞)

多线程优点

切换速度快、切换开销小
易于实现任务间的通信协作
提高并发度

多线程实现

  • 用户级线程:由程序自己实现,操作系统不参与调度
  • 内核级线程:内核级线程是在操作系统内核层对进程实现的多线程功能,操作系统以线程作为处理器调度和分派的基本单位
  • 混合式线程:某些操作系统提供了同时支持用户级线程与内核级线程的混合式线程设施,线程的创建、调度和同步在用户空间进行。一个应用程序中的多个用户级线程被映射到一些(小于或等于用户级线程的数目)内核级线程上。
处理器调度

处理器调度考虑两个问题:如何从多个作业中选择一些作业加载到内存中并为其创建进程?如何从多个进程中选择一个进程交由CPU处理

高级调度:从磁盘后备作业队列中挑选若干作业进入内存,为其分配资源,创建进程,决定一个进程能否被创建及创建后能否被置位就绪态

中级调度:决定哪些进程进入挂起状态,哪些进程从挂起状态中被唤醒,即决定哪些进程参与竞争处理器资源,哪些进程换出到磁盘,哪些进程从磁盘中换入内存

低级调度:决定哪一个就绪进程占用CPU,中断是执行低级调度的时机

调度时选择调度算法的因素

  • CPU利用率 = CPU有效工作时间/CPU总的运行时间
  • 吞吐率:单位时间内CPU处理的作业数
  • 公平性:至少确保不会出现饥饿现象(饥饿即调度时有的线程长时间占用不到CPU,对于用户来时就好像进程停止工作了一样)
  • 响应时间:从提交一个请求到接收到响应之间的时间间隔,响应时间 = 命令传输到CPU的时间+CPU处理命令的时间+处理结果返回终端的时间
  • 周转时间:作业提交给系统开始,到作业完成为止的时间间隔,即周转时间=完成时刻-提交时刻
  • 平均周转时间:n个作业的总周转时间/n
  • 带权周转时间:作业周转时间(总时间)/作业运行时间
  • 平均带权周转时间:n个作业的总带权周转时间/n

作业、进程和线程

作业对应一个完整的业务处理过程,该过程包含若干个相对独立又相互关联的顺序加工步骤,每个步骤对应着一个进程或线程

处理器调度算法

主要讲低级调度算法,可以分为两种类型:

  • 剥夺方式:由OS剥夺正在运行的程序,将CPU交给其它进程/线程使用。常见的有两种:高优先级剥夺:谁优先级高先运行谁;时间片剥夺:按时分方式时间片用完了就调度一次
  • 非剥夺方式:一旦某个进程或线程开始执行便不再出让处理器,除非该进程或线程运行结束或发生了某个事件不能继续执行。

两者一般混合使用,内核关键程序使用非剥夺方式、用户进程使用剥夺方式

调度算法

(1)先来先服务算法FCFS:谁先来就先服务谁,非剥夺

(2)最短作业优先算法SJF:对每一个到来的作业进行时间估计,那个时间最少就运行谁,非剥夺

(3)最短剩余时间优先算法SRTF:对每一个到来的作业进行时间估计,对当前时刻的所有进程进行时间评估,时间少的可抢占CPU优先处理,剥夺式

(4)响应比最高者优先算法HRRF:计算响应比,响应比 = 作业的响应时间/作业处理时间,选择响应比最高的先执行,非剥夺

(5)优先级调度算法:根据确定的优先级选取进程/线程,每次总是选择就绪队列中优先级最高者运行。

(6)轮转调度算法:每次把CPU分配给就绪队列首进程/线程使用一个时间间隔(称为时间片),就绪队列中的每个进程/线程轮流运行一个时间片。

并发进程的同步与互斥、死锁与饥饿

进程并发性:进程的并发性是指一组进程的执行在时间上是重叠的,即一个进程执行的第一条指令是在另一个进程执行的最后一条指令完成之前开始的。其实质是一个CPU在多个进程间复用,消除计算机部件之间的互等现象以提高系统资源利用率

  • 无关并发:一组并发进程分别在不同的变量集合上操作,一个进程的执行与其他并发进程的进展无关,即一个并发进程不会改变另一个并发进程的变量值。
  • 交互并发:一组并发进程共享某些变量,一个进程的执行可能影响其他并发进程的执行结果。

并发带来的问题

竞争CPU处理时间带来的问题(即进程指令执行顺序的先后):

  • 结果不唯一:同时处理一个共享变量导致对共享变量的操作不是原子性的
  • 永远等待:如等待进程错过了唤醒信号而永远等待的情况

竞争资源带来的问题:

  • 死锁:两个进程互相持有对方所需要的资源的同时又想获取对方持有的资源从而陷入永久等待的问题
  • 饥饿:一些进程总是优先于另一些进程,使某些进程陷入长久等待

进程互斥:指若干进程要使用同一共享资源时,任何时刻最多允许一个进程使用,其他要使用该资源的进程必须等待,直到占有资源的进程释放该资源。

进程同步:指两个以上进程基于某个条件协调彼此的活动,一个进程的执行依赖于协作进程的消息或信号,当一个进程没有得到来自于协作进程的消息或信号时需等待,直到消息或信号到达才被唤醒。即同步进程间必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。

临界区管理

临界区:并发进程中与共享变量有关的程序段叫做临界区,即一次只能有一个进程执行的程序段

临界资源:共享变量代表的资源叫做临界资源,不可共享资源

Peterson算法

Peterson算法是一个正确的临界区管理算法

bool inside[2];//标志对方进程是否进入临界区
inside[0]=false;
inside[1]=false;
enum {
   0,1} turn;//标志对方进程是否到达了临界区前
cobegin
process P0( )
{
   
  inside[0]=true;//标志该进程开始
  turn=1;
  while(inside[1]&&turn==1);//另一个进程开始但还没有更改turn时等待,一旦更改则那个进程等待而自己执行
  {
   临界区};
  inside[0]=false;
} 
process P1( )
{
   
inside[1]=true;
  turn=0;
  while(inside[0]&&turn==0);//等待
  {
   临界区};
  inside[1]=false;
}
coend

指令是顺序执行的,对于turn来说在临界区前只有一个值,根据turn的值来判断哪一个进程先进入临界区,对于上述程序来说,谁先更改turn谁就先执行,先执行的进程依赖于另一个进程更改turn的值。

实现临界区管理的硬件条件

硬件条件应该保证对于临界区的访问是互斥的

  • 关中断:进程在进入临界区之前先关中断,退出临界区时开中断。虽然简单但一般不使用,长时间关中断会影响系统效率且并不适用于多CPU系统

  • TS指令:

    TS(x)
    {
         
    若x=true,则x=false;return true;
    否则 return false;
    }
    

    该指令配合外部临界资源相当于一把锁,进入时上锁,退出时解锁

    bool s=true;//临界资源,相当于锁
    cobegin
    process Pi( )
    {
          //i=1,2,...,n
    while(!TS(s));    //上锁
    		{
         临界区};
    		s=true;//解锁
    }
    coend
    
  • 交换指令SWAP(a,b):

bool lock=false;//锁,只有开关两种状态,通过SWAP保证互斥
cobegin
Process Pi( )
{
   //i=1,2,...,n
	bool keyi=true;
	do
      {
   
   		SWAP(keyi,lock);//将两个值互换
      	}while(keyi); //上锁
	{
   临界区};
	SWAP(keyi,lock);//解锁
}
coend
信号量与PV操作

信号量:多个进程间可以通过简单的信号进行合作,可强迫一个进程在某个位置停止直到接收到一个特定的信号。

通常信号量的结构可以描述为:

typedef struct semaphore
{
   
     int value;        //信号量值
     struct pcb *list; //信号量队列指针
 } semaphore;

value表示可以进入临界区的进程的数量,>0表示还可以使用的资源数量,<0则表示正在等待的进程数量。list为指向阻塞的进程队列指针

P操作:表示请求进入临界区的操作:

void P(semaphore &s)
{
   
     s.value--;//如果<=0则直接将调用进程加入阻塞队列
     if(s.value<0)  W(s.list); //将P操作调用者进程置为阻塞状态并移入s信号量队列,转进程调度
}

V操作:表示从临界区出来,释放资源的操作:

void V(semaphore &s)
{
   
      s.value++;
      if(s.value<=0)  R(s.list);
      //从信号量s队列中释放一个等待信号量s的进程并转换成就绪态,自己则继续执行
}

使用PV操作实现互斥的基本步骤为

semaphore mutex;
mutex=1;
cobegin
process Pi( )
{
    //i=1,…,n
	P(mutex);
	{
   临界区};
	V(mutex);
}
coend
经典同步问题–哲学家进餐问题

为了吃面,每个哲学家必须获得两把叉子,且每人只能从自己左边或右边去取叉子。

laHGuT.png

错误的解决方法:

semaphore fork[5];//表示对每个叉子上锁
for (int i=0;i<5;i++)
fork[i]=1;
cobegin
process philosopher_i( )
{
    //i= 0,1,2,3,4
	while(true)
	{
   
		think( );
  		P(fork[i]);
	 	P(fork[(i+1)%5])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值