操作系统课程之“读者—写者”问题教学探讨
2011-12-31邱剑锋谢娟李龙澍汪继文李炜
计算机教育 2011年22期
摘 要:针对操作系统教学中概念多而繁杂、容易混淆,初学者存在畏难情绪等问题,文章提出采取类比、逐层解剖、层层深入、循序渐进的教学方法,并以操作系统中的进程同步互斥问题中“读者-写者”问题为例,对其概念、算法进行形象启发、分层解剖的阐述,并结合多种教学方法,说明使学生能更深刻地理解进程同步互斥问题的方法。教学实践表明其效果良好。
关键词:操作系统;分层解剖;读者-写者问题;PV原语;教学实践
操作系统是计算机专业的一门核心课程(图1),其在计算机系统中的特殊地位,使得该课程的学习在整个计算机学科教育中显得尤为重要。作为一门理论性和实践性并重的课程,它具有概念多、算法较抽象的特点,同时又涉及了程序设计语言、软件工程思想、算法设计、计算机系统结构、网络等相关知识。枯燥的理论讲述往往使学生感到抽象、难懂,进而产生厌学的思想。尽管近年来一些高校在加强理论教学的同时,引入对操作系统内核的分析,如Linux操作系统,在教学实践方面取得了一点的成效,但是对于初学者和教师而言,在一个学期内课时数不变的情况下,完成教与学的工作显得有点心有余而力不足。
为了在有限的教学时间内,提高教学效率,既让学生深入理解理论知识,又能借助PV操作原语来验证操作系统的算法思想,笔者根据以往教学经验,结
合初学者学习的实际情况,以进程同步中“读者-写者”为例,探讨如何由浅入深、循序渐进地开展教学工作。
1 问题描述
“读者—写者”问题是现代操作系统中经典的进程同步互斥问题,在以C/S模式为代表的多进(线)程通信系统都可以作为该模型的不同表现形式,有着广泛的应用[1]。该问题描述如下:
一个数据文件或记录可被多个进程所共享,我们将其中只要求读该文件的进程称为读者,即“Reader进程”,其他进程称为写者,即“Writer进程”。多个Reader进程和多个Writer进程在某个时间段内对该文件资源进行异步操作,也就是说允许多个进程同时读一个共享对象,但绝不允许一个Writer进程和其他Reader进程或Writer进程同时访问共享对象,因此,所谓“读者—写者问题”就是指必须保证一个Writer进程和其他进程(Writer进程和Reader进程)互斥地访问共享对象的同步问题[2]。两者的读写操作限制如下[3]:
1) 写—写互斥,即不允许多个写者同时对文件进行写操作;
2) 读—写互斥,即不允许读者和写者同时对文件分别进行读写操作;
3) 读—读允许,即允许多个读者同时对文件进行读操作。
基金项目:2009年国家级质量工程安徽大学计算机应用技术创新实验区项目(2009027042);安徽省教育厅教改项目(2008jyxm274);安徽省高等学校优秀青年人才基金项目资助(2011SQRL018);安徽大学青年科学研究基金(KJQN1015)。
作者简介:邱剑锋,男,讲师,研究方向为计算机操作系统、数据挖掘、信号与信息处理等。
2 分层解剖,降低难度
PV操作及同步互斥的实现是操作系统中重点难点内容之一,其中读者写者问题又是PV操作中经典的案例,为了使学生更好地理解这个知识点,在教学实践中,笔者采用分层解剖、化解难点、由浅到深的教学方法,取得了较好的教学效果。
“读者—写者”问题是一个有代表性的进程同步问题,作为初学者要做到透彻理解并不容易,但是如果我们将该问题进行细分,由简单到复杂,理解难度将大大降低,在每一种情况下都需要满足上述的读写规则。
1) 一个读者,一个写者共享一个数据文件。
为了更好地让学生理解,我们把抽象的问题具体化。将一个读者比喻为一个学生小明,而一个写者比喻为老师王老师,而一个数据文件比喻成一个公告版。在该情况下,可以理解为王老师负责修改布告版的内容,小明只能去阅读报告版的内容。王老师对布告版内容修改时小明不能去读,反之,小明读的时候王老师也不能去修改。显然,这是一个简单的互斥问题。
解决这个问题时,我们只需设置一个互斥信号量Wmutex,表示写进程与读进程互斥地访问数据文件,初值为1。
读进程:
while(TRUE){
P(Wmutex);
读数据文件;
V(Wmutex);
}
2) 一个读者,多个写者共享一个数据文件。
类似地,我们仍将一个读者比喻为学生小明,而这个时候写者有多个,这里以两个写者为例,分别称作王老师和赵老师,而数据文件仍比喻成公告版。在这里,小明和两位写者之间是互斥的,王老师和赵老师之间作为写者也是互斥地去访问数据文件,所以解决方法如第一种情况所示,在此不再赘述。
3) 多个读者,一个写者共享一个数据文件。
这里我们有多个读者,我们以两个为例,分别称之为小明和小强,而这个时候写者为一个称之为王老师,而数据文件仍比喻成公告版。根据读写规则,小明和小强可以同时访问数据文件,因为读是不会使数据文件发生混乱的,而王老师和小明、小强之间必须满足互斥,即只有当小明和小强都不读时,王老师才可以写数据文件,反之,当王老师执行写操作时,小明和小强中任一个人都不能执行读操作。
根据上述思路,我们给出以下解决方案,在保留写互斥信号量Wmutex基础上,增加共享变量Readcount,该变量记录当前正在读数据集的读进程数目,初值为0。此外,注意到Readcount是一个可被多个Reader进程访问的临界资源,因此也需对它进行互斥访问,设置一个读互斥信号量Rmutex,表示读进程互斥地访问共享变量Readcount,初值为1。算法描述为:
几点说明:
a. 这个时候允许多个读进程在读,而读和写是互斥的,所以必须有个变量记录读者的数目,Readcount就起到这个作用,即可以被多个读进程访问的临界资源,所以必须互斥访问。上述Reader( )过程中的两对P(Rmutex)、V(Rmutex)表示对Readecount这个共享变量的互斥访问操作。
b. 在Reader( )进程中,如果是第一个来访问的读者(通过Readcount来判断),执行P(Wmutex),阻止写者,防止在读的过程中受到写者的干扰。如果不是第一个来访问的读者,直接执行Readcount加1操作,因为按照规则,多个读者可以同时访问数据文件。类似地,在读完数据文件后,仍然先要去访问Readcount这个共享变量,如果不是最后一个读者,就不能释放资源Wmutex,反之则通过V(Wmutex)操作通知写者writer( )可以执行写操作。
4) 多个读者,多个写者共享一个数据文件。
这种情况和3)非常相似,虽然有多个写者去访问数据文件,但仍需满足读者和写者的互斥、写者和写者的互斥,所以该情况下的解决方案和3)相同,在此不再赘述。
3 引入管程机制解决“读者—写者”问题
通过分层教学,将难点层层解剖使学生理解了“读者—写者”的概念,此时注意引导、启发学生注意到在用信号量机制解决同步问题时,往往比较繁琐这样一个问题,很自然地引入到采用面向对象的程序设计思想,将资源及对资源的共享操作封装起来,即用管程来管理进程同步互斥问题,实现“读者—写者”问题,使用起来会更加方便。下面将实现的主要思想描述如下:
在具体使用管程机制来实现读者与写者问题时,首先建立一个管程,命名为ReaderWriter进程。其中包括以下几个过程:
1) Read( )过程。读者利用该过程获取数据块并拥有数据块中的数据,用整型变量ReaderCount来表示现在正在读取数据块中的数据的读者数量,当ReaderCount为0且条件变量MesState不为0或-1时,读者尚须等待。当ReaderCount大于0时,预示着当前数据块已被读者进程占有,条件变量MesState应
为1,此时其他读者可以进入数据块读取数据信息。
2) EndRead( )过程。读者读完数据后退出管程,释放数据资源,同时ReaderCount的数量做减1操作。当ReaderCount的数量不为0时,不允许写者占用该数据资源;当ReaderCount的数量变为0时,将mesStated的值更改为0,以示数据资源现处于空闲状态,允许读者和写者竞争该数据块资源。
3) Write( )过程。模拟写者利用该过程占有数据块以及获取数据块中的数据,写者可以修改数据。写者具有追加、删除、修改数据的权限。写者占有管程及数据块时条件变量MesState的值更改为-1,以示其他写者及所有读者均须等待该写者完成此次操作完成后,才有机会访问该资源,实现读者和写者的互斥、写者和写者的互斥。当写者完成写操作后,释放管程及数据块资源,将MesState的值更改为0,以唤醒在等待对列的其他进程竞争该资源。
4 结语
将操作系统中的一个复杂的进程同步与互斥问题分解成若干个简单的问题,由浅入深,层层解析,逐步扩展,在讲清基本概念之后,进一步采取启发式教学,进一步深化学生对该问题的认识。该教学方法符合教育教学规律,降低了难度,便于学生掌握课程的重难点,加深了关于同步问题的理解,提高了学习效率,教学效果也非常显著。
参考文献:
[1] Crow ley C P. Operating systems: a design-oriented approach [M]. Beijing:World Publishing