没有合适的资源?快使用搜索试试~ 我知道了~
操作系统课程设计读者写者问题.doc
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 118 浏览量
2022-07-13
10:22:19
上传
评论 1
收藏 69KB DOC 举报
温馨提示
试读
18页
操作系统课程设计读者写者问题.doc
资源推荐
资源详情
资源评论
. . .
1 / 18
操作系统课程设计——读者写者问题
一、实习要求
在 windows 2000 环境下,创建一个控制台进程,此进程包含 n 个线程。用这 n 个线程来表示 n 个读者或写
者。每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。用信号量机制分别实现读者优先和写者优
先的读者—写者问题。
读者—写者问题的读写操作限制(包括读者优先和写者优先):
1)写—写互斥,即不能有两个写者同时进行写操作。
2)读—写互斥,即不能同时有一个线程在读,而另一个线程在写。
3)读—读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开
始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等
到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一
行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、测试数据文件格式
测试数据文件包括 n 行测试数据,分别描述创建的 n 个线程是读者还是写者,以与读写操作的开始时间和持
续时间。每行测试数据包括四个字段,各个字段间用空格分隔。第—字段为—个正整数,表示线程序号。第二字
段表示相应线程角色,R 表示读者,W 表示写者。第三字段为一个正数,表示读写操作的开始时间:线程创建后,
延迟相应时间(单位为秒)后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线
程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。
下面是—个测试数据文件的例子:
1 R 3 5
2 W 4 5
3 R 5 2
4 R 6 5
5 W 5.1 3
注意 在创建数据文件时,由于涉与到文件格式问题,最好在记事本中手工逐个键入数据,而不要拷贝粘贴
数据,否则,本示例程序运行时可能会出现不可预知的错误。
三、实习分析
可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队
列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
1.读者优先
读者优先指的是除非有写者在写文件,否则读者不需要等待。所以可以用—个整型变量 readcount 记录当前
的读者数目,用于确定是否需要释放正在等待的写者线程(当 readcount=0 时,表明所有的读者读完,需要释放
写者等待队列中的一个写者)。每一个读者开始读文件时,必须修改 readcount 变量。因此需要一个互斥对象
mutex 来实现对全局变量 readcount 修改时的互斥。
另外,为了实现写—写互斥,需要增加一个临界区对象 RP_Write。当写者发出写请求时,必须申请临界区
对象的所有权。通过这种方法,也可以实现读—写互斥、当 readcount=1 时(即第一个读者到来时),读者线程也
必须申请临界区对象的所有权。
当读者拥有临界区的所有权时,写者阻塞在临界区对象 RP_Write 上。当写者拥有临界区的所有权时,第一
个读者判断完“readcount= =1”后阻塞在 write 上,其余的读者由于等待对 readcount 的判断,阻塞在 mutex
上。
. . .
2 / 18
2.写者优先(请根据自己编写的写者优先程序进行分析)
四、相关 API 函数说明
1.CreateThread
函数功能:
该函数创建一个在调用进程的地址空间中执行的线程。
函数原型:
HANDLE CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
参数:
·lpThreadAttributes:指向一个 LPSECURITY_ATTRIBUTES 结构。该结构决定了返回的句柄是否可被子进程
继承。若 lpThreadAttributes 为 NULL,则句柄不能被继承。
在 Windows NT 中该结构的 lpSecurityDescriptor 成员定义了新进程的安全性描述符。若
lpThreadAttributes 为 NULL。则线程获得—个默认的安全性描述符。
·dwStackSize:定义原始堆栈提交时的大小(按字节计)。系统将该值舍入为最近的页。若该值为 0,或小
于默认时提交的大小,默认情况是使用与调用线程同样的大小.更多的信息,请看 Thread Stack Size。
·lpStartAddress:指向一个 LPTHREAD_START_ROUTINE 类型的应用定义的函数,该线程执行此函数。该指
针还表示远程进程中线程的起始地址。该函数必须存在于远程进程中。
·lpParameter:定义一个传递给该进程的 32 位值。
·dwCreationFlags:定义控制进程创建的附加标志。若定义了 CREATE_SUSPENDED 标志,线程创建时处于挂
起状态,并且直到 ResumeThread 函数调用时才能运行。若该值为 0,则该线程在创建后立即执行。
·lpThreadId:指向—个 32 位值,它接收该线程的标识符。
返回值:
若函数调用成功,返回值为新线程的句柄;若函数调用失败,返回值为 NULL。
备注:
新进程的句柄创建时设为 THREAD_ALL_ACCESS 访问权限。若未提供安全性描述符,则该句柄可被任何要求一
个线程对象句柄的函数所使用。若提供了安全性描述符,则以后使用该句柄时,将在授权访问以前执行访问检查。
若访问检查拒绝访问,则请求进程不能使用该句柄获得对该线程的访问。
线程从 lpStartAddress 参数定义的函数处开始执行。若该函数返回,系统将默认地认为以调用 ExitThread
函数的方法终止该线程。使用 GetExitcodeThread 函数来获得线程的返回值。
线程创建时拥有 THREAD_PRIORITY_NORMAL 优先权。使用 GetThreadPriority 和 SetThreadPriority 函数可
以获得和设置线程的优先权值。
一个线程终止时。该线程对象被设为发信号状态,以满足在该对象上等待的所有进程。
一个线程对象始终存在于系统中,直到该线程终止,且它所有的句柄都已通过调用 CloseHandle 函数关闭。
2.ExitThread
函数功能:
该函数结束一个线程。
函数原型:
VOID ExitThread (DWORD dwExitCode);
参数:
·dwExitCode:定义调用线程的退出代码。使用 GetExitCodeThread 函数来检测一个线程的退出代码。
返回值:无。
备注:
. . .
3 / 18
调用 ExitThread 函数,是结束—个线程的较好的方法。调用该函数后(或者直接地调用,或者从一个线程过
程返回),当前线程的堆栈取消分配,线程终止。若调用该函数时,该线程为进程的最后一个线程,则该线程的
进程也被终止。
线程对象的状态变为发信号状态,以释放所有正在等待该线程终止的其他线程。线程的终止状态从
STILL_ACTIVATE 变为 dwExitCode 参数的值。
线程结束时不必从操作系统中移去该线程对象。当线程的最后一个句柄关闭时,该线程对象被删除。
3.Sleep
函数功能:
该函数对于指定的时间间隔挂起当能的执行线程。
函数原型:
VOID Sleep (DWORD dwMulliseconds);
参数:
·dwMilliseconds:定义挂起执行线程的时间,以毫秒(ms)为单位。取值为 0 时,该线程将余下的时间片交
给处于就绪状态的同一优先级的其他线程。若没有处于就绪状态的同一优先级的其他线程,则函数立即返回,该
线程继续执行。若取值为 INFINITE 则造成无限延迟。
返回值:
该函数没有返回值。
备注:
一个线程可以在调用该函数时将睡眠时间设为 0ms,以将剩余的时间片交出。
4.CreateMutex
函数功能:
该函数创建有名或者无名的互斥对象。
函数原型:
HANDLE CreateMutex (LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner, LPCTSTR lpName);
参数:
·lpMutexAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,该结构决定子进程是否能继承返回句柄。
如果 lpMutexAttributes 为 NULL,那么句柄不能被继承。
在 Windows NT 中该结构的 LpSecuriyDescriptor 成员指定新互斥对象的安全描述符。如果
lpMutexAttributes 为 NULL,那么互斥对象获得默认的安全描述符。
·bInitialOwner:指定互斥对象的初始所属身份。如果该值为 TRUE,并且调用者创建互斥对象,那么调用
线程获得互斥对象所属身份。否则,调用线程不能获得互斥对象所属身份。判断调用者是否创建互斥对象清参阅
返回值部分。
·lpName:指向以 NULL 结尾的字符串,该字符串指定了互斥对象名。该名字的长度小于 MAX_PATH 且可以包
含除反斜线(\)路径分隔符以外的任何字符。名字是区分大小写的。
如果 lpName 与已存在的有名互斥对象名相匹配,那么该函数要求用 MUTEX_ALL_ACCESS 权限访问已存在的对
象。在这种情况下,由于参数 bInitialOwner 已被创建进程所设置,该参数被忽略。如果参数 lpMutexAttributes
不为 NULL,它决定句柄是否解除继承,但是其安全描述符成员被忽略。
如果 lpName 为 NULL,那么创建的互斥对象无名。
如果 lpName 与已存在的事件、信号量、可等待定时器、作业或者义件映射对象的名字相匹配,那么函数调
用失败,并且 GetLastError 函数返回 ERROR_ALREADY_HANDLE,其原因是这些对象共享一样的名字空间。
返回值:
如果函数调用成功,返回值是互斥对象句柄;如果函数调用之前,有名互斥对象已存在,那么函数给已存在
的对象返回一个句柄,并且函数 GetLastError 返回 ERROR_ ALREADY_EXISTS。否则,调用者创建互斥对象。
. . .
4 / 18
如果函数调用失败,则返回值为 NULL。若想获得更多错误信息,请调用 GetLastError 函数。
备注:
由函数 CreateMutex 返回的句柄有 MUTEX_ALL_ACCESS 权限可以去访问新的互斥对象,并且可用在请求互斥
对象句柄的任何函数中。
调用进程中的任何线程可以在调用等待函数时指定互斥对象句柄。当指定对象的状态为信号态时。返回单对
象等待函数。当任何一个或者所有的互斥对象都为信号态时,返回多对象等待函数指令。等待函数返回后,等待
的线程被释放,继续向下执行。
当一个互斥对象不被任何线程拥有时,处于信号态。创建该对象的线程可以使用 bInitialOwner 标志来请求
立即获得对该互斥对象的所有权。否则,线程必须使用等待函数来请求所有权。当互斥对象处于信号态,等待的
线程获得对该对象的所有权时,此互斥对象的状态被设置为非信号态,等待函数返回。任意时刻,仅有一个线程
能拥有该互斥对象.线程可以使用 ReleaseMutex 函数来释放对这个互斥对象的所有权。
总线程已经拥有了—个互斥对象,那么它可以重复调用等待函数而不会发生阻塞,一般情况下,用户不会重
复等待同一个互斥对象,这种机制防止了线程因等待它已经拥有的互斥对象而发生死锁。然而,线程必须为每一
次等待调用—次 ReleaseMutex 函数来释放该互斥对象。
两个或多个进程可以调用 CreateMutex 来创建同名的互斥对象,第一个进程实际创建互斥对象.以后的进程
打开已存在的互斥对象的句柄。这使得多个进程可以得到同一个互斥对象的句柄,从而减轻了用户的负担,使用
户不必判断创建进程是否为第一个启动的进程。使用这种技术时,应该把 bInitialOwner 标志设为 FALSE;否则
很难确定开始时哪一个进程拥有该互斥对象。
由于多进程能够拥有一样互斥对象的句柄,通过使用这个对象,可使多进程同步。以下为共享对象机制:
·如果 CreateMutex 中的 lpMutexAttributes 参数允许继承,由 CreateProcess 函数创建的子进程可以继承
父近程的互斥对象句柄。
·一个进程可以在调用 DuplicateHandle 函数时指定互斥对象句柄来创建一个可以被其他进程使用的双重
句柄。一个进程在调用 OpenMutex 或 CreateMutex 函数时能指定互斥对象名。
·使用 CloseHandle 函数关闭句柄,进程结束时系统自动关闭句柄。当最后一个句柄被关闭时,互斥对象被
销毁。
5.ReleaseMutex
函数功能:
该函数放弃指定互斥对象的所有权。
函数原型:
BOOL ReleaseMutex (HANDLE hMutex);
参数:
·hMutex:互斥对象句柄。为 CreateMutex 或 OpenMutex 函数的返回值。
返回值:
如果函数调用成功,那么返回值是非零值;如果函数调用失败,那么返回值是零值。若想获得更多错误信息,
请调用 GetLastError 函数。
备注:
如果调用线程不拥有互斥对象,ReleaseMutex 函数失败。
一个线程通过调用等待函数拥有互斥对象。创建该互斥对象的线程也拥有互斥对象。而不需要调用等待函数。
当互斥对象的所有者线程不再需要互斥对象时,它可以调用 ReleaseMutex 函数。
当—个线程拥有—个互斥对象后,它可以用该互斥对象多次调用等待函数而不会阻塞。这防止一个线程等待
一个它已拥有的互斥对象时出现死锁。不过,为了释放所有权,该线程必须为每一个等待操作调用一次
ReleaseMutex 函数;
6.WaitForSingleObject
函数功能:
剩余17页未读,继续阅读
资源评论
智慧安全方案
- 粉丝: 3676
- 资源: 59万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功