清华大学操作系统讲义第04讲_经典IPC问题

合集下载

ch04_Thread-1pp 操作系统 讲义

ch04_Thread-1pp 操作系统 讲义

线程的概念第4章线程n g S y s t e m s , B J U T4.1概述传统进程资源分配的单位在CPU 上执行的单位: 一个控制线索n g S y s t e m s , B J U T 为什么引入线程概念? 引入进程的目的使多个进程并发执行改善资源利用率提高系统吞吐量 问题提出一个应用程序可能需要执行多个不同的或相似的任务创建多个进程进程的创建进程的创建、、切换切换、、撤销 时空开销 引入线程的原因程序并发执行时所付出的时空开销↓n g S y s t e m s , B J U T 线程(Thread)轻量级进程(lightweight process, LWP) 使用CPU 的基本单位控制线索在CPU 上执行的单位 包含线程ID程序计数器(PC)寄存器集合栈 属于同一进程的各线程, 共享该进程的资源 代码段, 数据段, 打开的文件, ……n g S y s t e m s , B J U T多线程进程n g S y s t e m s , B J U T 多线程环境下的进程和线程 进程资源分配的单位保护的单位 线程进程中的一个实体调度和分派的基本单位只拥有运行所必须的资源 PC, 一组寄存器, 栈与同进程内的其他线程与同进程内的其他线程共享进程所拥有的资源共享进程所拥有的资源 基本状态: 运行运行、、就绪就绪、、阻塞n g S y s t e m s , B J U T 多线程的优点提高并发性响应度高共享资源 经济—降低时空开销同一进程的多个线程共享地址空间同一进程的多个线程共享地址空间、、资源 线程的创建线程的创建、、撤销撤销、、切换—开销小 易于调度线程间通信效率高 多处理器体系结构利用 一进程的多个线程可在不同处理器上并行执行n g S y s t e m s , B J U T4.2 多线程模型用户线程与内核线程 多线程模型 多对一模型 一对一模型 多对多模型 二级模型n g S y s t e m s , B J U T用户线程用户级线程库管理线程 User threads are supported above the kernel and are managed without kernel support.n g S y s t e m s , B J U T内核线程Kernel threads are supported andmanaged directly by the operating systemn g S y s t e m s , B J U Tn g S y s t e m s , B J U Tn g S y s t e m s , B J U T多对多模型n g S y s t e m s , B J U T二级模型n g S y s t e m s , B J UT Multithreaded Server Architecture (补充) 线程池n g S y s t e m s , B J U TConcurrent Execution on a Single-core Systemn g S y s t e m s , B J UT Parallel Execution on a Multicore Systemn g S y s t e m s , B J U T 本章其余内容自学 推荐编程实践。

U034计算机操作系统教程_第四版_(张尧学著)_清华大学出版社_第4章

U034计算机操作系统教程_第四版_(张尧学著)_清华大学出版社_第4章

2. 带权周转时间 作业的周转时间包含了两个部分,即等待时间和执 行时间。为了更进一步反映调度性能,使用带权周 转时间的概念。带权周转时间是作业周转时间与作 业执行时间的比: Wi=Ti/Tri 对于被测定作业流所含有的几个作业来说,其平均 1 n 带权周转时间为:
W= W n
i =1 i
对于分时系统,除了要保证系统吞吐量大、资源利 用率高之外,还应保证有用户能够容忍的响应时间。 因此,在分时系统中,仅仅用周转时间或带权周转 时间来衡量调度性能是不够的。
4.1.2 调度的层次 处理机调度问题实际上也是处理机的分配问题。显 然,只有那些参与竞争处理机所必需的资源都已得 到满足的进程才能享有竞争处理机的资格。这时, 它们处于内存就绪状态。这些必需的资源包括内存、 外设及有关数据结构等。从而,在进程有资格竞争 处理机之前,作业调度程序必须先调用存储管理、 外设管理程序,并按一定的选择顺序和策略从输入 井中选择出几个处于后备状态的作业,为它们分配 内存等资源和创建进程,使它们获得竞争处理机的 资格。
4.3 进 程 调 度
无论是在批处理系统还是分时系统中,用户进程数 一般都多于处理机数,这将导致用户进程互相争夺 处理机。另外,系统进程也同样需要使用处理机。 这就要求进程调度程序按一定的策略,动态地把处 理机分配给处于就绪队列中的某一个进程,以使之 执行。本节介绍进程调度的功能、进程调度发生的 时机以及由进程调度引起的进程上下文切换等。
4.3.1 进程调度的功能 进程调度的具体功能可总结如下: (1) 记录系统中所有进程的执行情况 作为进程调度的准备,进程管理模块必须将系统中 各进程的执行情况和状态特征记录在各进程的PCB 表中。并且,进程管理模式根据各进程的状态特征 和资源需求,将各进程的PCB表排成相应的队列并 进行动态队列转接。进程调度模块通过PCB变化来 掌握系统中所有进程的执行情况和状态特征,并在 适当的时机从就绪队列中选择出一个进程占据处理 机。

编程实现经典IPC问题

编程实现经典IPC问题

实验原理:(含相关算法流程图,可写多页)生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。

在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

问题的实质是P、V操作,实验设一个共享缓冲区,当一个线程使用缓冲区的时候,另一个让其等待直到前一个线程释放缓冲区为止。

读者作家(RW)或共享独占锁(也称为多个读取器/单写入器锁定或多读卡器锁)的一个同步原语,解决了一个读者-writers问题。

一个RW锁允许并发的只读操作的访问,而写操作需要独占访问。

这意味着多个线程可以并行读出的数据,但独占锁是需要编写或修改数据。

当一个作家写数据,直到作家写完所有其他作家或读者将被阻止。

一个常见的用途可能是用于控制访问存储器中的数据结构不能被更新原子和是无效的(不应该由另一个线程被读取),直到完成更新。

读者作家锁通常建在上面互斥和条件变量,或在顶部信号量。

void main(){HANDLE hp[num];HANDLE hc[num];InitializeCriticalSection(&cs);empty=CreateSemaphore(NULL,5,5,NULL);full=CreateSemaphore(NULL,0,5,NULL);for(int n=0;n<num;n++){hp[n]=CreateThread(NULL,0,Threadp,reinterpret_cast<LPVOID>(n),0,NULL); printf("%d producer created\n",n);hc[n]=CreateThread(NULL,0,Threadc,reinterpret_cast<LPVOID>(n),0,NULL);printf("%d consumer created\n",n);}WaitForMultipleObjects(num,hp,TRUE,INFINITE);WaitForMultipleObjects(num,hc,TRUE,INFINITE);CloseHandle(empty);CloseHandle(full);}# include <windows.h># include <iostream.h># include <stdio.h># include <stdlib.h>HANDLE stick[5];const int num=5;static DWORD WINAPI p(LPVOID lp){ LONG n=reinterpret_cast<LONG>(lp);Sleep(100-n);printf("philosopher%d want to eat . \n",n);WaitForSingleObject(stick[n],INFINITE);printf("philosopher%d take one stick. \n",n);WaitForSingleObject(stick[(n+1)%5],INFINITE);printf("philosopher%d is eating . \n",n);Sleep(n*100);printf("philosopher%d eat end . \n",n);ReleaseMutex(stick[n]);ReleaseMutex(stick[(n+1)%5]);return(0); }void main(){ HANDLE hp[num];for(int n=0;n<num;n++){ stick[n]=CreateMutex(NULL,FALSE,NULL);hp[n]=CreateThread(NULL,0,p,reinterpret_cast<LPVOID>(n),0,NULL); printf("philosopher%d created.\n",n);CloseHandle(hp);}WaitForMultipleObjects(num,hp,TRUE,INFINITE);for( n=0;n<5;n++) CloseHandle(stick[n]);}}ReleaseMutex(rmutex);ReleaseMutex(wmutex);WaitForMultipleObjects(num,rh,TRUE,INFINITE); WaitForMultipleObjects(num,wh,TRUE,INFINITE); CloseHandle(rmutex);CloseHandle(wmutex);}。

计算机操作系统第四版课件

计算机操作系统第四版课件

计算机操作系统第四版课件计算机操作系统是计算机科学与技术领域的一门重要课程,涉及到计算机系统的核心原理和基本概念。

为了帮助学生更好地学习和理解这门课程,编写一份精美的课件是非常必要的。

本文将按照合适的格式来书写计算机操作系统第四版课件,以提供给学生们一份有条理、易于理解的学习资料。

第一章介绍在第一章中,我们将介绍计算机操作系统的基本概念和定义。

通过这一章的学习,学生将对计算机操作系统有一个初步的了解。

1.1 什么是计算机操作系统计算机操作系统是一种控制和管理计算机硬件资源的软件系统。

它为用户提供了一个操作界面,使得用户可以通过操作系统来管理计算机。

1.2 操作系统的作用操作系统有许多重要的作用,包括管理和分配计算机的硬件资源、提供用户接口、控制程序执行和文件管理等。

1.3 操作系统的组成操作系统由内核和外壳组成。

内核负责管理和控制计算机的核心功能,而外壳则提供给用户一个友好的界面。

第二章进程管理在第二章中,我们将详细介绍进程管理这一重要概念。

进程管理是操作系统的核心功能之一。

2.1 进程的定义和特点进程是指正在执行的程序在计算机上的一次执行过程。

每个进程都有其自己的一些特点,如进程的状态、优先级和资源需求等。

2.2 进程调度进程调度是操作系统中的一个重要组成部分。

它负责决定每个进程在运行时的先后顺序。

2.3 进程同步与通信在多道程序环境下,进程之间的同步与通信是非常重要的。

操作系统提供了一些机制来实现进程之间的同步和通信。

第三章内存管理在第三章,我们将着重介绍内存管理这一与操作系统密切相关的概念。

3.1 内存的基本概念内存是计算机中的一种存储设备,用于存储程序和数据。

我们将介绍内存的基本概念,包括虚拟内存、逻辑地址和物理地址等。

3.2 内存分配与回收内存分配和回收是操作系统中的重要工作之一。

操作系统需要负责管理内存的分配和回收,以确保系统的稳定性和性能。

3.3 页面置换算法在内存不足的情况下,操作系统需要使用页面置换算法来选择哪些页面被置换出去,以便为新的页面腾出空间。

2024版计算机操作系统第四版ppt课件

2024版计算机操作系统第四版ppt课件

分布式处理系统的应用
如云计算、大数据处理等。
分布式文件系统与数据库系统
分布式文件系统的基本概念
01
将文件分布在多个计算机节点上,通过网络进行访问和
管理。
分布式数据库系统的基本概念
02
将数据库分布在多个计算机节点上,通过网络进行访问
和管理,同时保持数据的一致性和完整性。
分布式文件系统和数据库系统的关键技术
文件共享是指多个用户或进程可以同时访问和使用同一文件。
文件保护
文件保护是指操作系统采取一定的措施,防止文件被非法访问、修 改或破坏。
共享与保护的实现方法
操作系统可以通过访问控制列表(ACL)、权限位和加密等机制来 实现文件的共享和保护。
文件操作及实现方法
文件操作
文件操作包括文件的创建、打开、读/写、定位和关闭等。
调度算法的性能评价指标
包括系统吞吐量、处理机利用率、周转时间、响应时间等。
典型的多处理机调度算法
如最短作业优先算法、最高响应比优先算法等。
分布式处理系统的特点与分类
分布式处理系统的特点
自治性、并发性、资源共享、透 明性等。
分布式处理系统的分类
根据系统中计算机的类型和互连 方式,可分为同构型分布式系统 和异构型分布式系统。
并行处理系统的基本结构 包括多个处理单元、互连网络、存储器等部件,通过相互 协作完成并行任务。
并行处理系统的分类 根据处理单元的数量和互连方式,可分为共享内存系统和 分布式内存系统。
多处理机调度算法及性能评价
多处理机调度算法的种类
包括静态调度算法和动态调度算法,其中动态调度算法又可分为集中式调度和分布式调度。
进程调度算法的实现需要考虑系统 效率、公平性和实时性等因素。

清华大学郑纬民老师的计算机体系结构chpt4

清华大学郑纬民老师的计算机体系结构chpt4
PDF 文件使用 "FinePrint pdfFactory Pro" 试用版本创建
目前使用的DMA方式实际上有如下三种: (1) 周期窃取方式 在每一条指令执行结束时,CPU测试 有没有DMA服务申请 借用CPU完成DMA工作流程.包括数 据和主存地址的传送,交换个数计数器减 1,主存地址的增值及一些测试判断等 周期窃取方式不需要使用程序来完成 数据的输入或输出,只借用一个CPU的周 期来完成DMA流程 周期窃取方式的优点是硬件结构简 单,比较容易实现
计算机系统结构
第一章 基本概念 第二章 指令系统 第三章 存储系统 第五章 标量处理机 第六章 向量处理机 第七章 互连网络 第八章 并行处理机

第四章 输入输出系统 第九章 多处理机
PDF 文件使用 "FinePrint pdfFactory Pro" 试用版本创建
PDF 文件使用 "FinePrint pdfFactory Pro" 试用版本创建
缺点是在数据输入或输出过程种实际 上占用了CPU的时间 (2) 直接存取方式 整个DMA工作流程全部在DMA控制 器中用硬件完成 直接存取方式的优点与缺点正好与周 期窃取方式相反 (3) 数据块传送方式 在设备控制器中设置一个比较大的数 据缓冲存储器.设备控制器与主存储器之 间的数据交换以数据块为单位,并采用程 序中断方式进行
PDF 文件使用 "FinePrint pdfFactory Pro" 试用版本创建
(4)在DMA方式开始和结束时,需要处理 机进行管理 (5)在DMA方式中,数据的传送过程不需 要CPU的干预 输入设备ID 输出设备OD I/O 主存储 存储器 处理机 CPU 总线 器MM 总线

清华大学操作系统课件_向勇老师的讲义

清华大学操作系统课件_向勇老师的讲义

• 考试:70%
– 基本原理+实践能力
• 先修课要求:
– 计算机组成原理、数据结构
• 上课要求:
– 请关闭您的手机,以免影响上课; – 上课时请不要开小会;
第一章 绪论
1.1 什么是操作系统 1.2 操作系统的发展历史 1.3 操作系统的特征 1.4 操作系统的功能 1.5 操作系统的结构 1.6 常用的操作系统
多道批处理系统的特点
• 优点:
– 资源利用率高:CPU和内存利用率较高; – 作业吞吐量大:单位时间内完成的工作总量大;
• 缺点:
– 用户交互性差:整个作业完成后或中间出错时, 才与用户交互,不利于调试和修改; – 作业平均周转时间长:短作业的周转时间显著增 长;
批处理:交互性差--提高对CPU利用率; 分时处理:用户与应用程序随时交互,控制程序运行,适于商 业和办公事务处理--缩短响应时间
返回
1.2.2 手工操作
1946 ~ 50年代(电子管),集中计算(计算中心),计算机 资源昂贵;
• 工作方式
– 用户:用户既是程序员,又是操作员;用户是计算 机专业人员; – 编程语言:为机器语言; – 输入输出:纸带或卡片;
• 计算机的工作特点
– 用户独占全机:不出现资源被其他用户占用,资源 利用率低; – CPU等待用户:计算前,手工装入纸带或卡片;计 算完成后,手工卸取纸带或卡片;CPU利用率低; 返回
1.1.2 操作系统的作用
• OS是计算机硬件、软件资源的管理者; • OS是用户使用系统硬件、软件的接口; • OS是扩展机/虚拟机;
返回
OS是计算机硬件、软件资源的管理者
• 管理对象包括:CPU、存储器、外部设备、信 息(数据和软件); • 管理的内容:资源的当前状态(数量和使用 情况)、资源的分配、回收和访问操作,相 应管理策略(包括用户权限)。

操作系统第4章ppt课件

操作系统第4章ppt课件

THANKS
感谢观看
P/V操作
对信号量进行加减操作,实现进程同 步与互斥。
经典同步问题及其解决方法
1 2
生产者-消费者问题
通过两个信号量分别控制生产者和消费者进程, 确保生产者和消费者之间的同步与互斥。
哲学家进餐问题
通过引入资源分级法或信号量集机制,避免死锁 的发生,确保哲学家进餐过程中的同步与互斥。
3
读者-写者问题

多线程模型比较分析
01
多对一模型Leabharlann 将多个用户级线程映射到一个内核级线程上。该模型下,线程管理在用
户空间完成,线程的调度采用非抢占式调度,由线程库负责。
02
一对一模型
将每个用户级线程都映射到一个内核级线程上。该模型下,线程的创建
、撤销和同步等都在内核中实现,线程的调度由内核完成。
03
多对多模型
将多个用户级线程映射到少数但不止一个内核级线程上。该模型结合了
前两种模型的优点,允许多个用户级线程映射到不同的内核级线程上运
行。
线程同步与互斥机制
互斥锁
采用互斥对象机制,只有拥有互斥对象的线程才有访问公共 资源的权限。因为互斥对象只有一个,所以能保证公共资源 不会同时被多个线程同时访问。
信号量
信号量是一个整型变量,可以对其执行down和up操作,也 就是常见的P和V操作。信号量初始化为一个正数,表示并发 执行的线程数量。
死锁避免:银行家算法是一种典型的 死锁避免算法。该算法通过检查请求 资源的进程对资源的最大需求量是否 超过系统可用资源量来判断是否分配 资源给该进程。如果分配后系统剩余 资源量仍然能够满足其他进程的最大 需求量,则分配资源,否则不分配资 源。
死锁检测:通过定期运行死锁检测算 法来检测系统中是否存在死锁。常见 的死锁检测算法有资源分配图算法和 银行家算法等。如果检测到死锁发生 ,则需要采取相应措施来解除死锁, 例如通过撤销部分进程或抢占部分资 源来打破死锁状态。

清华大学UNIX讲义第4章

清华大学UNIX讲义第4章
int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++)
printf("%d: [%s]\n", i, argv[i]);
}
编译、链接以生成可执行文件。使用命令: cc arg.c -o arg 或者使用命令: make arg 在当前目录下生成名为 arg的可执行文件 ,没有 Windows系统中那样的.EXE扩展名。执行这个程 序的命令,如: ./arg abc ABCDEF
shell程序也是在操作系统内核支持下的应用级程序, 与普通用户编写的C语言源程序编译链接之后产生 的可执行程序在系统中有相同的地位。甚至,用户 也可以根据自己的喜好编写自己的shell程序。从设 计shell软件的程序员角度看,在shell提示符下输入 命令,会在程序中得到一个字符串的输入,这是第 一步;将得到的这个字符串进行加工处理,其中, 含有对文件名通配符的展开工作,生成结果命令, 这是第二步;第三步,调用操作系统的系统调用, 创建新的进程执行命令,并把参数传递给新进程。
(2)关于文件扩展名。DOS中*.*匹配所有文件, UNIX中*.*要求文件名中必须含有句点,否则不匹 配。UNIX中并没有把文件名中的句点做特殊的处 理,它和普通的字符有着相同的地位。UNIX文件 名处理中,没有所谓“扩展名”的概念。 (3)匹配子目录中的文件。在UNIX中可以使用 */*.[ch]通配符,匹配当前目录下所有一级子目录 中文件名后缀为.c和.h的文件,这在DOS中不允许。
路 /unix 径 程序文件,UNIX 内核 供系统维护管理用的命令和配置文件。例如: 文件/etc/passwd:存放的是用户相关的配置信息; 文件/etc/issue:登录前在 login 之上的提示信息; 文件/etc/motd:存放登录成功后显示给用户的信息。 文件系统管理的程序有 fsck,mount,shutdown 等。 许多系统维护的命令,在不同的 UNIX 系统之间区别很大 /tmp,/usr/tmp /bin /dev /usr/include /usr/bin 存放临时文件 系统常用命令,如 ls,ln,cp,cat 等 存放设备文件,如终端设备文件,磁带机,打印机等 C 语言头文件存放目录 存放一些常用命令,如 ftp,make 等 存放各种库文件,包括 C 语言的链接库文件,动态链接库, 还包括与终端类型相关的 terminfo 终端库,等等。静态链接 库文件有.a 后缀, 动态链接库文件的后缀不是.DLL, 而是.so。 UNIX 很早就广泛地使用动态链接库,静态链接库逐渐过 时。.a 取名于 archive(存档),.so 取名于 shared objects(共 享对象) 存放与用户有关的一些临时性文件,如: 打印队列,已收到但未 读的邮件等 说 明

ipc段计算

ipc段计算

ipc段计算摘要:1.IPC 段计算的概述2.IPC 段计算的原理3.IPC 段计算的应用4.IPC 段计算的优缺点正文:1.IPC 段计算的概述IPC(Inter Process Communication)段计算,即进程间通信段计算,是一种计算机程序设计中的技术。

它主要用于实现多进程或多线程之间的通信和协同工作。

在进程间通信中,IPC 段计算起到了数据传输和共享的作用,使得各个进程可以相互传递数据和信息,协同完成任务。

2.IPC 段计算的原理IPC 段计算主要基于计算机内存的管理和操作。

在进程运行过程中,操作系统会为每个进程分配一块独立的内存空间,以保证进程之间的数据不互相干扰。

IPC 段计算通过共享内存或者消息传递等方式,实现进程间的数据交流。

共享内存:多个进程可以访问同一块内存区域,实现数据的共享。

这种方式的优点是数据访问速度快,但缺点是容易造成数据混乱和进程死锁。

消息传递:进程之间通过发送和接收消息来实现通信。

这种方式的优点是较为安全,缺点是数据访问速度相对较慢。

3.IPC 段计算的应用IPC 段计算在实际应用中具有广泛的应用价值,主要体现在以下几个方面:(1)多进程协同:在多进程程序设计中,各个进程需要相互配合,共同完成任务。

通过IPC 段计算,各个进程可以相互传递数据和信息,实现协同工作。

(2)跨进程数据共享:在多进程程序设计中,有时需要实现跨进程的数据共享。

通过IPC 段计算,可以实现多进程之间的数据共享,提高程序运行效率。

(3)进程间同步与通信:IPC 段计算可以实现进程间的同步和通信,避免因为进程执行顺序不当导致的程序错误。

4.IPC 段计算的优缺点优点:(1)提高了程序的运行效率:通过IPC 段计算,实现了进程间的数据共享和通信,避免了数据重复计算,提高了程序的运行效率。

(2)增强了程序的可扩展性:通过IPC 段计算,可以方便地实现多进程协同工作,使得程序的设计和实现更加灵活,具有更好的可扩展性。

ipc段计算

ipc段计算

ipc段计算(最新版)目录1.IPC 的概念与含义2.IPC 段计算的原理与方法3.IPC 段计算的应用实例4.IPC 段计算的优缺点正文一、IPC 的概念与含义IPC(Inter Process Communication)即进程间通信,是指在计算机系统中,多个进程之间进行数据传输和共享的过程。

进程间通信是操作系统中的一个重要功能,它使得各个进程可以相互协作,共同完成任务。

IPC 机制可以分为两大类:同步通信和异步通信。

同步通信主要包括互斥锁、信号量等;异步通信则包括管道、消息队列、套接字等。

二、IPC 段计算的原理与方法IPC 段计算,是指在进程间通信过程中,对进程所处的段(Section)进行计算。

这里的“段”是操作系统中的一个重要概念,是指内存中一段连续的区域,可以被一个或多个进程共享。

在 IPC 段计算中,主要涉及到两种类型的段:共享段(Shared Section)和未共享段(Unshared Section)。

1.共享段:多个进程可以访问同一个共享段,这种方式可以实现进程间的数据共享。

共享段中的数据在各个进程中是独立存在的,因此当一个进程对共享段中的数据进行修改时,不会影响到其他进程。

2.未共享段:每个进程都有自己的未共享段,这些段中的数据是独立的,不会被其他进程访问。

未共享段主要用于存储各个进程的私有数据。

在 IPC 段计算中,主要是通过操作系统提供的内存映射(Memory Mapping)机制来实现的。

具体来说,就是将共享段映射到各个进程的地址空间,使得进程可以通过访问本地内存来访问共享段中的数据。

三、IPC 段计算的应用实例IPC 段计算在实际应用中具有广泛的应用,例如在多线程或多进程程序设计中,可以使用 IPC 段计算来实现进程间或线程间的数据共享和通信。

具体来说,可以通过以下步骤来实现:1.创建共享段:通过操作系统提供的 API,创建一个共享段,并将其映射到各个进程的地址空间。

IPC典型模型-哲学家纠缠问题

IPC典型模型-哲学家纠缠问题

IPC典型模型-哲学家纠缠问题1965年dijkstra提出了⼀个关于进程同步问题,⼤致意思如下:有5个哲学家坐在⼀张圆桌上,每个哲学家左右两边各有⼀个叉⼦。

只有当集齐两个叉⼦,才能够吃饭,否则哲学家就得乖乖去思考。

桌⼦上就5个叉⼦,理论上同时可以让两个哲学家进餐,那么怎么⽤两个进程来模拟这个状态呢?0x001这⼏个哲学家可以视作⼀个进程开了5次。

我们来创建⼀个哲学家进程,代码如下: ⽤_tagCOMMUNICATIONOBJECT存放公共的数据,放在公共的内存中。

#include "stdafx.h"#include <Windows.h>#include<iostream>#define EATING_TIME 1000#define PHILOSOPHER_COUNT 5#define WM_INVALIDATE WM_USER + 1//公⽤的数据,放到映射的内存中的数据using namespace std;typedef struct _tagCOMMUNICATIONOBJECT{HWND hWnd;bool bExitApplication;int iPhilosopherArray[PHILOSOPHER_COUNT];int PhilosopherCount;} COMMUNICATIONOBJECT, * PCOMMUNICATIONOBJECT;void Eat();//吃饭饭TCHAR* szSemaphoreName = TEXT("__PD_SEMAPHORE__");//信号量名称TCHAR* szMappingName = TEXT("__SHARED_FILE_MAPPING__");//映射内存名称bool bExitApplication = false;//退出应⽤标志int _tmain(int argc, _TCHAR* argv[]){//获取控制台句柄HWND Hconsole = GetConsoleWindow();ShowWindow(Hconsole, SW_HIDE);//隐藏控制台窗⼝int index = (int)_tcstol(argv[0], NULL, 10);//获取当前进程代号//读取映射内容HANDLE hMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szMappingName);if (!hMapping){cout << "hMapping打开失败!" << endl;cout << GetLastError() << endl;return -1;}//映射内容⼀旦打开,未关闭时,⼀直处于可操作状态while (!bExitApplication){//打开信号量HANDLE hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, szSemaphoreName);if (!hSemaphore){cout << "sempahore创建失败!" << endl;cout << GetLastError() << endl;return -1;}//等待信号量触发WaitForSingleObject(hSemaphore, INFINITE);//等待信号对象//从映射对象中读取通⽤变量PCOMMUNICATIONOBJECT pcomobj = (PCOMMUNICATIONOBJECT)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(COMMUNICATIONOBJECT));if (!pcomobj){cout << "pcomobj创建失败!" << endl;cout << GetLastError() << endl;return -1;}bExitApplication = pcomobj->bExitApplication;//获取循环标志if (!pcomobj->iPhilosopherArray[(index + pcomobj->PhilosopherCount - 1) % pcomobj->PhilosopherCount] &&!pcomobj->iPhilosopherArray[(index + pcomobj->PhilosopherCount + 1) % pcomobj->PhilosopherCount]){pcomobj->iPhilosopherArray[index] = 1;Eat();//吃饭}SendMessage(pcomobj->hWnd, WM_INVALIDATE, 0, 0);//向另⼀个窗⼝发送消息pcomobj->iPhilosopherArray[index] = 0;//吃完饭置为0ReleaseSemaphore(hSemaphore, 1, NULL);//针对⼀个信号量UnmapViewOfFile(pcomobj);//关闭⽂件映射CloseHandle(hSemaphore);//关闭信号量句柄}CloseHandle(hMapping);//关闭⽂件映射句柄return 0;//返回}void Eat(){Sleep(EATING_TIME);//停顿⼀段时间⽤于吃饭}0x02创建⼀个进程来控制哲学家进餐#include "stdafx.h"#include<iostream>using namespace std;#define BUTTON_CLOSE 100#define PHILOSOPHER_COUNT 5#define WM_INVALIDATE WM_USER + 1typedef struct _tagCOMMUNICATIONOBJECT{HWND hWnd;bool bExitApplication;int iPhilosopherArray[PHILOSOPHER_COUNT];int PhilosopherCount;} COMMUNICATIONOBJECT, *PCOMMUNICATIONOBJECT;HWND InitInstance(HINSTANCE hInstance, int nCmdShow);ATOM MyRegisterClass(HINSTANCE hInstance);LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);int PhilosopherPass(int iPhilosopher);void FillEllipse(HWND hWnd, HDC hDC, int iLeft, int iTop, int iRight, int iBottom, int iPass);TCHAR* szTitle = TEXT("Philosophers Dinner Demo");TCHAR* szWindowClass = TEXT("__PD_WND_CLASS__");TCHAR* szSemaphoreName = TEXT("__PD_SEMAPHORE__");TCHAR* szMappingName = TEXT("__SHARED_FILE_MAPPING__");PCOMMUNICATIONOBJECT pCommObject = NULL;int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {//未使⽤的变量不出现警告UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);HANDLE hMapping = CreateFileMapping((HANDLE)-1, NULL,PAGE_READWRITE, 0, sizeof(COMMUNICATIONOBJECT), szMappingName);if (!hMapping){cout << "hMapping为空!" << endl;cout << GetLastError() << endl;return -1;}pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);if (!pCommObject){cout << "pcommobject为空!" << endl;cout << GetLastError() << endl;return -1;}HANDLE hSemaphore = CreateSemaphore(NULL, (PHILOSOPHER_COUNT / 2),(PHILOSOPHER_COUNT / 2),szSemaphoreName);if (!hSemaphore){cout << "hsemaphore为空!" << endl;cout << GetLastError() << endl;return -1;}InitCommonControls();//初始化通⽤控件MyRegisterClass(hInstance);//注册HWND hwnd = InitInstance(hInstance,nCmdShow);//初始化if (!hwnd){cout << "hwnd为空!" << endl;cout << GetLastError() << endl;return -1;}pCommObject->hWnd = hwnd;pCommObject->bExitApplication = false;pCommObject->PhilosopherCount = PHILOSOPHER_COUNT;memset(pCommObject->iPhilosopherArray, 0,sizeof(*pCommObject->iPhilosopherArray));//开启进程STARTUPINFO starupinfo[PHILOSOPHER_COUNT] = { {0},{0},{0},{0},{0} };PROCESS_INFORMATION processInfo[PHILOSOPHER_COUNT]= { {0},{0},{0},{0},{0} };HANDLE hProcess[PHILOSOPHER_COUNT] = { 0 };TCHAR szBuffer[8] = {0};for (int i = 0; i < PHILOSOPHER_COUNT; i++){wsprintf(szBuffer, TEXT("%d"), i);if (CreateProcess(TEXT("..\\Debug\\Philosopher.exe"), szBuffer, NULL,NULL,FALSE,NULL,NULL,NULL,&starupinfo[i],&processInfo[i])){hProcess[i] = processInfo[i].hProcess;}}MSG msg = { 0 };while (GetMessage(&msg, hwnd, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}pCommObject->bExitApplication = true;UnmapViewOfFile(pCommObject);//关闭⽂件映射for (int i = 0; i < PHILOSOPHER_COUNT; i++){CloseHandle(hProcess[i]);//关闭进程句柄}CloseHandle(hMapping);return (int)msg.wParam;//返回消息参数0}//ATOM==wordATOM MyRegisterClass(HINSTANCE hInstance){WNDCLASSEX wndEx;wndEx.cbSize = sizeof(WNDCLASSEX);wndEx.style = CS_HREDRAW | CS_VREDRAW;wndEx.lpfnWndProc = WndProc;wndEx.cbClsExtra = 0;wndEx.cbWndExtra = 0;wndEx.hInstance = hInstance;wndEx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));wndEx.hCursor = LoadCursor(NULL, IDC_ARROW);wndEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);wndEx.lpszMenuName = NULL;wndEx.lpszClassName = szWindowClass;wndEx.hIconSm = LoadIcon(wndEx.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));return RegisterClassEx(&wndEx);}//初始化HWND InitInstance(HINSTANCE hInstance, int nCmdShow){HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED | WS_CAPTION| WS_SYSMENU | WS_MINIMIZEBOX, 200, 200, 540, 590, NULL, NULL, hInstance, NULL);if (!hWnd){return NULL;}HFONT hFont = CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, TEXT("Microsoft Sans Serif"));HWND hButton = CreateWindow(TEXT("BUTTON"), TEXT("Close"), WS_CHILD | WS_VISIBLE| BS_PUSHBUTTON | WS_TABSTOP, 410, 520, 100, 25, hWnd, (HMENU)BUTTON_CLOSE, hInstance, NULL);SendMessage(hButton, WM_SETFONT, (WPARAM)hFont, TRUE);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return hWnd;}//回调函数LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){switch (uMsg){case WM_COMMAND:{switch (LOWORD(wParam)){case BUTTON_CLOSE:{DestroyWindow(hWnd);break;}}break;}case WM_INVALIDATE:{//更新指定的窗⼝区域InvalidateRect(hWnd, NULL, TRUE);//接受philosopher发来的消息,进⾏处理break;}case WM_PAINT:{PAINTSTRUCT paintStruct;HDC hDC = BeginPaint(hWnd, &paintStruct);FillEllipse(hWnd, hDC, 210, 10, 310, 110, PhilosopherPass(1));//圆圈1FillEllipse(hWnd, hDC, 410, 170, 510, 270, PhilosopherPass(2));//圆圈2FillEllipse(hWnd, hDC, 335, 400, 435, 500, PhilosopherPass(3));//圆圈3FillEllipse(hWnd, hDC, 80, 400, 180, 500, PhilosopherPass(4));//圆圈4FillEllipse(hWnd, hDC, 10, 170, 110, 270, PhilosopherPass(5));//圆圈5EndPaint(hWnd, &paintStruct);//结束绘制break;}case WM_DESTROY:{PostQuitMessage(0);break;}default:{return DefWindowProc(hWnd, uMsg, wParam, lParam);}}return 0;}//哲学家int PhilosopherPass(int iPhilosopher){return pCommObject->iPhilosopherArray[iPhilosopher - 1];}//填充圆圈void FillEllipse(HWND hWnd, HDC hDC, int iLeft, int iTop, int iRight, int iBottom, int iPass) {HBRUSH hBrush = NULL;if (iPass)//哲学家状态⾮0,填充红⾊{hBrush = CreateSolidBrush(RGB(255, 0, 0));}else//哲学家状态为0,填充⽩⾊{hBrush = CreateSolidBrush(RGB(255, 255, 255));}HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);//选中画刷1Ellipse(hDC, iLeft, iTop, iRight, iBottom);//绘制圆形SelectObject(hDC, hOldBrush);//填充颜⾊DeleteObject(hBrush);//⽤完之后清空选中的句柄}。

第4讲、操作系统-经典的IPC问题

第4讲、操作系统-经典的IPC问题

Page 17
操作系统-进程与线程
一、生产者-消费者问题 2.3.5 信号量
Semaphore empty = N, full = 0;
void producer( void ) { int item; while ( TRUE ) { item = produce_item(); down(&empty); insert_item( item ); up(&full); } }
办法:
多个生产者,一个一个放。 多个消费者,一个一个拿。
Page 20
操作系统-进程与线程
一、生产者-消费者问题 2.3.5 信号量
Semaphore empty = N, full = 0, mutex = 1; void producer( void ) { int item; while ( TRUE ) { item = produce_item(); down(&empty); down(&mutex); insert_item( item ); up(&mutex); up(&full); } } void consumer( void ) { int item; while ( TRUE ) { down(&full); down(&mutex); item = get_item( item ); down(&mutex); up(&empty); consume_item(item); } }
《操 作 系 统》
第二章 进程与线程
--经典的IPC问题
目录
一、信号量
二、生产者消费者问题
三、哲学家进餐问题 四、读写者问题

清华大学操作系统课件_向勇老师的讲义

清华大学操作系统课件_向勇老师的讲义
第二章 作业管理和用户接口
在这一章中,我们讨论OS向上提供的用户接口,即系 统命令接口和系统调用接口。系统命令接口可完成用 户作业的组织和控制。
2.1 作业组织和控制 2.2 UNIX的作业管理 2.3 系统调用 2.4 图形用户接口
1
2.1 作业组织和控制
2.1.1 作业和作业处理过程 2.1.2 作业调度 2.1.3 作业控制语言
• 命令简化:利用参数替换可简化命令输入,通 配符(?, *)用于匹配一组文件名
– 如:UNIX的cp命令:当前目录上有两个"1.tar"和 "2.tar"时,"cp *.tar /tmp"等同于"cp 1.tar /tmp; cp 2.tar /tmp"
15
2. 环境变量
环境变量(environment variable)--应用进程地址空间中的特殊 变量区。
21
3. 基本特征
• 内部命令:如cd, exec――区分大小写,exec的 功能是执行一个命令; • 外部命令:如/bin/ls, /bin/mkdir • 命令行选项通常是:-option
– 如:"ls -a -l"中的-a表示列出所有文件,-l表示列出 所有信息。
• 通配符:由shell处理后再传递给外部命令。
– 如:cat *.c 则argv[1]="a.c", argv[2]="b.c",而 cat "*.c" 则argv[1]="*.c"(cat的功能是读入所有文件,并 显示)
22
4. 输入输出重定向
基于内核的缓冲区
• "<"为标准输入重定向; • ">"和">>"为标准输出重定向; • "2>"和"2>>"为标准错误输出重定向(2表示标 准错误输出的设备号,只对sh有意义); • " >&"是标准输出和标准错误输出重定向; 行输入重定向:用定界符间的内容作为标准输入。 如:下面命令的标准输入为cat命令的输入。 cat << WARNING ... 23 WARNING

IPC经典问题76

IPC经典问题76
END;
PROCEDURE wait(VAR instance:one_instance;VAR s:semephore;VAR count:integer); BEGIN
count++; IF instance.urgent_count>0 THEN BEGIN
instance.urgent_count--; V(instance.urgent) END ELSE V(instance. mutex); P(s); END;
if (state[ i ] == HUNGRY) && (state [ (i-1) % 5] != EATING) && (state [ (i+1) % 5] != EATING) { state[ i ] = EATING; V(&s[ i ]); }
}
void philosopher (int i)
名字表 use 本管程外所定义、本管程内将调用的过程(函数)
名字表
PROCEDURE 过程名(形参表); 过程局部变量说明; BEGIN 语句序列; END;
......
管程的形式(续)
FUNCTION 函数名(形参表):值类型; 函数局部变量说明; BEGIN 语句序列; END;
...... BEGIN
V(mutex); };
写者: while (true) {
P(w); 写
V(w);
};
第一类读者写者问题的解法 (一般信号量集)
读者:
写者:
Swait(wmutex,1,1; rcount,R,0);
写; Ssignal(wmutex,1);
Swait(rcount,1,1; wmutex,1,0);

清华大学操作系统向勇老师的讲义

清华大学操作系统向勇老师的讲义

四个进程在并发地运行
3. 进程与程序的区别
• 进程是动态的,程序是静态的:程序是有序代码 的集合;进程是程序的执行。通常进程不可在计 算机之间迁移;而程序通常对应着文件、静态和 可以复制。
• 进程是暂时的,程序的永久的:进程是一个状态 变化的过程,程序可长久保存。
• 进程与程序的组成不同:进程的组成包括程序、 数据和进程控制块(即进程状态信息)。
第四章 进程管理
为了描述程序在并发执行时对系统资源的共享,我们需要一个 描述程序执行时动态特征的概念,这就是进程。在本章中,我 们将讨论进程概念、进程控制和进程间关系。
4.1 进程(PROCESS) 4.2 进程控制 4.3 线程(THREAD) 4.4 进程互斥和同步 4.5 进程间通信(IPC, INTER-PROCESS
– 顺序执行是单道批处理系统的执行方式,也用于 简单的单片机系统;
– 现在的操作系统多为并发执行,具有许多新的特 征。引入并发执行的目的是为了提高资源利用率 并适应多任务处理的要求。
• 顺序执行的特征
– 顺序性:按照程序结构所指定的次序(可能有分支或循环)
– 封闭性:独占全部资源,计算机的状态只由于该程序的控 制逻辑所决定
– 可再现性:初始条件相同则结果相同。如:可通过空指令 控制时间关系。
• 并发执行的特征
– 间断(异步)性:"走走停停",一个程序可能走到中途停下 来,失去原有的时序关系;
– 失去封闭性:共享资源,受其他程序的控制逻辑的影响。 如:一个程序写到存储器中的数据可能被另一个程序修改, 失去原有的不变特征。
• 动态性:进程具有动态的地址空间(数量和内容), 地址空间上包括:
– 代码(指令执行和CPU状态的改变) – 数据(变量的生成和赋值) – 系统控制信息(进程控制块的生成和删除)

计算机操作系统课后习题答案第四版

计算机操作系统课后习题答案第四版

计算机操作系统课后习题答案第四版在学习计算机操作系统这门课程时,课后习题是巩固知识、检验理解的重要环节。

下面,我们将对第四版教材中的一些典型课后习题进行详细的解答。

首先来看第一章的习题。

其中有一道关于操作系统定义和功能的题目。

操作系统可以被理解为是管理计算机硬件与软件资源的程序,它负责控制和协调计算机系统中各个部件的工作,为用户和应用程序提供一个方便、高效、安全的操作环境。

其主要功能包括处理机管理、存储器管理、设备管理、文件管理以及用户接口管理等。

比如处理机管理,它要合理地分配处理机时间,以提高系统的运行效率;存储器管理则要确保内存的合理分配和有效利用,避免出现内存泄漏等问题。

第二章中,有涉及进程概念和进程状态转换的习题。

进程是操作系统进行资源分配和调度的基本单位。

它具有动态性、并发性、独立性和异步性等特征。

进程在其生命周期中会经历不同的状态,如就绪、运行和阻塞。

当一个进程具备了运行所需的资源和条件,它就处于就绪状态,等待被调度执行;一旦获得处理机,就进入运行状态;而当进程由于等待某个事件的发生而无法继续执行时,就会进入阻塞状态。

在第三章的习题里,有关线程的问题较为常见。

线程是进程中的一个执行单元,它可以共享进程的资源,从而提高系统的并发性能。

与进程相比,线程的创建和切换开销更小,因此在多线程编程中被广泛应用。

例如,在一个网络服务器中,可以为每个连接创建一个线程来处理数据的接收和发送,提高服务器的响应速度。

第四章的存储管理部分,有关于分页存储管理和分段存储管理的习题。

分页存储管理将内存空间划分成固定大小的页,而分段存储管理则是根据程序的逻辑结构将其划分成不同的段。

分页存储管理的优点是便于内存管理和分配,但可能会产生内部碎片;分段存储管理则更符合用户的编程思维,但会存在外部碎片。

在实际应用中,往往会结合两者的优点,形成段页式存储管理。

第五章的设备管理中,涉及到设备驱动程序和I/O 控制方式的问题。

操作系统课后习题第四

操作系统课后习题第四

操作系统课后习题第四操作系统课后习题第四一、进程管理1、进程与线程1.1 进程的定义和特点1.2 线程的定义和特点1.3 进程和线程的区别与联系2、进程控制块(PCB)2.1 PCB的作用和内容2.2 PCB的创建和销毁过程2.3 PCB的状态转换3、进程调度算法3.1 先来先服务调度(FCFS)3.2 短作业优先调度(SJF)3.3 时间片轮转调度(RR)3.4 优先级调度(Priority)3.5 多级反馈队列调度(MFQ)4、进程同步4.1 进程间的竞争关系4.2 临界区问题4.3 同步与互斥4.4 进程同步的方法4.4.1 互斥量4.4.2 信号量4.4.3 事件4.4.4 屏障二、内存管理1、内存分配方式1.1 静态分配1.2 动态分配1.2.1 分区分配1.2.2 页式存储管理1.2.3 段式存储管理1.2.4 段页式存储管理2、内存替换算法2.1 最优页面置换算法(OPT)2.2 先进先出页面置换算法(FIFO)2.3 最近最久未使用页面置换算法(LRU)2.4 时钟页面置换算法(Clock)3、虚拟内存管理3.1 页面置换算法的选择3.2 页面调度3.3 页面置换的策略3.4 页面置换算法的性能评估三、文件系统管理1、文件的组织和操作1.1 文件的逻辑结构1.2 文件的物理结构1.3 文件的操作1.3.1 创建文件1.3.2 打开与关闭文件1.3.3 读写文件2、文件目录2.1 目录的作用和组织方式 2.2 目录的操作2.2.1 创建目录2.2.2 查找目录项2.2.3 删除目录项2.2.4 更改目录项3、文件系统的实现3.1 单级目录结构3.2 两级目录结构3.3 树目录结构3.4 图目录结构附件:无法律名词及注释:1、PCB(Process Control Block):进程控制块,操作系统内部维护的用于管理进程的数据结构,记录了进程的基本信息和状态。

2、FCFS(First-Come, First-Served):先来先服务调度算法,根据进程到达时间的先后顺序进行调度。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
10
第二,把信号量视为是某种类型的共享资源的剩 余个数,其目的是为了实现对这种类型的共享资 源的访问,如各种I/O设备。信号量的取值具有实 际的意义,就等于空闲资源的个数。多个进程可 以同时使用这种类型的资源,直到所有空闲资源 均已用完。其特征是信号量的初始值为N(N1), 然后在一个进程内部对它进行配对的P、V操作。
28
思路(2) 计算机程序怎么来解决这个问题?
指导原则:不能浪费CPU时间;进程间相互通信。 S1 思考中… S2 进入饥饿状态; S3 如果左邻居或右邻居正在进餐,进入阻塞状态; 否则转S4 S4 拿起两把叉子; S5 吃面条… S6 放下左边的叉子,看看左邻居现在能否进餐 (饥饿状态、两把叉子都在),若能则唤醒之; S7 放下右边的叉子,看看右邻居现在能否进餐, 若能,唤醒之; S8 新的一天又开始了,转S1
操作系统与系统编程
第四讲
谌 卫 军
清华大学软件学院 2004年春季
1
基于信号量的进程同步
【例子2】共享缓冲区的合作进程的同步
设有一个缓冲区buffer,大小为一个字节。Compute 进程不断产生字符,送buffer,Print进程从buffer中 取出字符打印。如不加控制,会出现多种打印结果, 这取决于这两个进程运行的相对速度。在这众多的 打印结果中,只有Compute和Print进程的运行刚好 匹配的一种是正确的,其它均为错误。 Compute buffer
6
流程图1:
get t0 t1 copy t2 put t3 get t4 copy t5 put t6
流程图2:
规则4 规则5
规则1
p
p
p
c
g
规则2
c
g
规则3
c
g
7
信号量的定义 semaphore S_Get; // 当前数据的Get操作是否 // 已完成,初值为0
semaphore S_Copy_Old; // 上一个数据的Copy操作 // 是否已完成,初值为1
临界区C1; V(S); 进程P1
配对
P(S); 临界区C2; 先后 进程P2
12
2.4 经典的IPC问题
生产者—消费者问题
哲学家就餐问题
读者—写者问题
睡着的理发师问题
用信号量来解决,主要问题:如何选择信号量, 如何安排P、V原语的顺序。
13
2.4.1 生产者—消费者问题
问题描述
两个进程(生产者和消费者)共享一个公有 的、固定大小的缓冲区,生产者不断地制造 产品,并把它放入缓冲区,而消费者不断地 把产品取出来,并且使用它。要求这两个 进程相互协调,正确地完成各自的工作。
这种相互等待,并互通信息就是典型的进程同步。 同时,缓冲区是个临界资源,因此,各个进程在 使用缓冲区的时候,还有一个互斥的问题。
16
信号量的定义
semaphore S_Buffer_Num; // 空闲的缓冲区个数, // 初值为N
semaphore S_Product_Num; // 缓冲区当中的产品个 // 数,初值为0 semaphore S_Mutex; // 用于互斥访问的信号 // 量,初值为1
18
消费者进程 void consumer(void) { int item; while(TRUE) { P(S_Product_Num); P(S_Mutex); item = remove_item( ) V(S_Mutex); V(S_Buffer_Num); consume_item(item); } }
不出现相邻者同时要求进餐,也不出现有人永远拿 不到叉子。
22
方案1 不正确,可能导致死锁。 #define N 5 // 哲学家个数 void philosopher(int i) // 哲学家编号:0 - 4 { while(TRUE) { think( ); // 哲学家在思考 take_fork(i); // 去拿左边的叉子 take_fork((i + 1) % N); // 去拿右边的叉子 eat( ); // 吃面条中…. put_fork(i); // 放下左边的叉子 put_fork((i + 1) % N); // 放下右边的叉子 } }
3
compute
print
compute
print
compute print
t0
t1
t2
t3
t4
t5
t6
semaphore S_Empty; // 缓冲区是否为空,初值为1 semaphore S_Full; // 是否有数据写入,初值为0 while(计算未完成) { P(S_Empty); Write_Data( ); V(S_Full); } Compute while(打印未完成) { P(S_Full); Print_Data( ); V(S_Empty); } Print
19
// 缓冲区中有无产品
// 进入临界区 // 从缓冲区取产品 // 离开临界区
// 新增一个空闲缓冲区
// 使用该产品
2.4.2 哲学家就餐问题
1965年,由Dijkstra提出并解决,后来逐渐
成为该领域的一个经典问题,或者说,是一
块试金石,用来试验新的进程同步方法的优
劣。
20
问题描述
五个哲学家围坐在一张圆桌 旁,每个哲学家面前都摆着 一大盘意大利面条,面条非 常滑,所以每个哲学家都需 要两把叉子才能进餐,在相 邻两个盘子之间,只有一把 叉子。 桌面的布局见右图。 0 0 4
4
【例子3】 三个并发进程的读写
输入缓冲区
输出缓冲区
• get进程负责从输入序列f中读取字符,送到输 入缓冲区S中; • copy进程把输入缓冲区S中的数据复制到输出 缓冲区T; • put进程从输出缓冲区T中取出数据打印。
5
问题分析:
为保证三个并发进程的正确运行,必须遵循以下 的五条同步规则: 1. 在每一个数据上的操作顺序为get - copy - put;
semaphore S_Copy_New; // 本次数据的Copy操作是 // 否已完成,初值为0 semaphore S_Put; // 上一个数据的Put操作是 // 否已完成,初值为1
8
while(…) { P(S_Copy_Old); Get_Data(f, s); V(S_Get); } Get while(…) { P(S_Copy_New); Put_Data(t, g); V(S_Put); } Put
2
Print
解题步骤:
1. 分析问题,弄清楚同步关系; 2. 设置信号量,说明其含义和初值; 3. 写出程序描述。
问题分析:
要保证打印结果的正确,Compute和Print进程必 须遵循以下同步规则:
1. 当Compute把数据送入buffer后,Print才能从 buffer中取,否则它必须等待(先存后取); 2. 当Print从buffer取走数据后,Compute才能将 新数据送buffer,否则也须等待(先取后存)
1
1
2
2 3 3
4
本图摘自 “Modern Operating Systems”
21
问题描述(续)
每个哲学家的动作只有两种:进餐和思考。当一个
哲学家感到饥饿时,他试图去获得他左边和右边的
两把叉子(一次取一把,顺序无关),然后才能开
始进餐。吃完以后,他需要把两把叉子放回原处,
然后继续思考。
问题是:如何保证哲学家们的动作有序进行?如:
23
方案2 对拿叉子的过程进行了改进,但仍不正确 while(1) // 去拿两把叉子 { take_fork(i); // 去拿左边的叉子 if(fork((i+1)%N)) { // 右边叉子还在吗 take_fork((i + 1) % N);// 去拿右边的叉子 break; // 两把叉子均到手 } else { // 右边叉子已不在 put_fork(i); // 放下左边的叉子 wait_some_time( ); // 等待一会儿 } }
14
消费者
生产者
8 7
1
2
消费方向
生产方向
6
3
5
4
生产—消费者问题
15
问题分析
对于生产者进程:制造一个产品,当要送入缓冲区 时,要检查缓冲区是否已满,若未满,才可将产品 送入缓冲区,并在必要时通知消费者;否则等待;
对于消费者进程:当它去取产品时,先要检查缓冲 区中是否有产品可取,若有,则取走一个,并在必 要时通知生产者;否则等待。
resource的初 P(resource); 值为N。 使用该资源; V(resource); 非临界区 // 申请使用一个资源
// 释放该资源
11
第三,把信号量作为进程间同步的工具,利用它 来设定两个进程在运行时的先后顺序。比如说, 它可以是某个共享资源的当前个数,但是由一个 进程负责生成该资源,而另一个进程负责消费该 资源,由此引发了两个进程之间的先后顺序。其 特征是信号量的初始值为N(N 0),然后在一 个进程里面用对它使用V原语,增加资源个数, 而在另外一个进程里面对它使用P原语,减少资 源个数,从而实现两个进程之间的同步关系。
2. 只有当s中的旧数据被copy取走后,get才能将 新数据送进来,否则就必须等待;
3. 只有当get把新数据送到s当中后,copy才能把 该数据取走,否则也必须等待; 4. 只有当t中的旧数据被put取走后,copy才能把 新数据从s拷贝到t当中,否则等待;
5. 只有当copy把新数据送入到t中后,put才能把 该数据取出打印,否则等待。
26
方案4的缺点:
它把就餐(而不是叉子)看成是必须互斥访问的 临界资源,因此会造成(叉子)资源的浪费。从 理论上说,如果有五把叉子,应允许两个不相邻 的哲学家同时进餐。
相关文档
最新文档