《2022年操作系统实验二 .pdf》由会员分享,可在线阅读,更多相关《2022年操作系统实验二 .pdf(5页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、实验二并发与调度一、实验目的在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000 线程同步的理解。通过分析实验程序,了解管理事件对象的API。了解在进程中如何使用事件对象,在进程中如何使用互斥体对象,线程如何通过文件映射对象发送数据。在 Linux Redhat 9.0操作系统平台上,用pipe() 创建一个管道文件,然后用fork()创建两个生产进程和两个消费进程,它们之间通过pipe() 传递消息。二、实验环境硬件环境:计算机一台,局域网环境;软件环境: Windows 2000 Professional,Linux Redhat 9.0 操作系统平台,Visual
2、C+ 6.0企业版。三、实验内容和步骤第一部分:互斥体对象本程序中显示的类CCountUpDown使用了一个互斥体来保证对两个线程间单一数值的访问。 每个线程都企图获得控制权来改变该数值,然后将该数值写入输出流中。创建者实际上创建的是互斥体对象,计数方法执行等待并释放,为的是共同使用互斥体所需的资源(因而也就是共享资源) 。利用互斥体保护共享资源/ mutex 项目# include # include class CCountUpDown public: CCountUpDown(int nAccesses) : m_hThreadInc(INV ALID_HANDLE_VALUE) , m
3、_hThreadDec(INVALID_HANDLE_VALUE) , m_hMutexValue(INV ALID_HANDLE_VALUE) , m_nValue(0) , m_nAccess(nAccesses) m_hMutexValue = : CreateMutex( NULL, TRUE, NULL) ; m_hThreadInc = : CreateThread( NULL, 0, IncThreadProc, reinterpret_cast (this) , 0, NULL) ; m_hThreadDec = : CreateThread( NULL, 0, DecThre
4、adProc, reinterpret_cast (this) , 0, NULL) ; : ReleaseMutex(m_hMutexValue) ; virtual CCountUpDown() : CloseHandle(m_hThreadInc) ; : CloseHandle(m_hThreadDec) ; : CloseHandle(m_hMutexValue) ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 5 页 - - - - - - - - - v
5、irtual void WaitForCompletion() if (m_hThreadInc != INVALID_HANDLE_VALUE & m_hThreadDec != INVALID_HANDLE_VALUE) : WaitForSingleObject(m_hThreadInc, INFINITE) ; : WaitForSingleObject(m_hThreadDec, INFINITE) ; protected: virtual void DoCount(int nStep) while (m_nAccess 0) : WaitForSingleObject(m_hMut
6、exValue, INFINITE) ; m_nValue += nStep; std : cout “thread: ” : GetCurrentThreadId() “value: ” m_nValue “access: ” m_nAccess std : endl;-m_nAccess; : Sleep(1000) ; / 使显示速度放慢: ReleaseMutex(m_hMutexValue) ; static DWORD WINAPI IncThreadProc(LPVOID lpParam) CCountUpDown* pThis = reinterpret_cast (lpPar
7、am) ; pThis - DoCount(+1) ; return(0) ; static DWORD WINAPI DecThreadProc(LPVOID lpParam) CCountUpDown* pThis = reinterpret_cast (lpParam) ; pThis - DoCount(-1) ; return(0) ; protected: HANDLE m_hThreadInc; HANDLE m_hThreadDec; HANDLE m_hMutexValue; int m_nValue; int m_nAccess ; ; void main() CCount
8、UpDown ud(50) ; ud.WaitForCompletion() ; 分析程序的运行结果,可以看到线程(加和减线程 ) 的交替执行(因为 Sleep() API 允许Windows 切换线程 ) 。在每次运行之后,数值应该返回初始值(0) ,因为在每次运行之后写入线程在等待队列中变成最后一个,内核保证它在其他线程工作时不会再运行。1) 请描述运行结果(如果运行不成功,则可能的原因是什么?) :_ _ 2) 根据运行输出结果,对照分析程序,可以看出程序运行的流程吗?请简单描述:_ _ 第二部分线程通过文件对象发送数据Windows 2000 提供的线程间通讯类内核对象允许同一进程或跨
9、进程的线程之间互相发送信息,包括文件、文件映射、邮件位和命名管道等,其中最常用的是文件和文件映射。这类对象允许一个线程很容易地向同一进程或其他进程中的另一线程发送信息。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 5 页 - - - - - - - - - 演示线程通过文件对象发送数据# include # include static LPCTSTR g_szFileName = “w2kdg.Fileobj.file.data.txt ” ; static DWOR
10、D WINAPI ThreadProc (LPVOID lpParam) LONG nAdd = reinterpret_cast (lpParam) ; TCHAR szFullName MAX_PA TH ; : GetTempPath(MAX_PA TH, szFullName) ; / 取得路径: strcat(szFullName, g_szFileName) ; HANDLE hFile = : CreateFile( szFullName, / 文件的完全名称GENERIC_READ | GENERIC_WRITE, / 具有所有的访问权FILE_SHARE_READ, / 允许
11、其他线程读取NULL, / 缺省的安全性OPEN_ALWAYS, / 创建或打开文件FILE_A TTRIBUTE_NORMAL, / 普通文件NULL) ; / 无模板文件if (hFile != INV ALID_HANDLE_VALUE) LONG nValue(0) ; DWORD dwXfer(0) ; : ReadFile( hFile, / 要读取的文件reinterpret_cast (&nValue) , / 缓冲区sizeof(nValue) , / 缓冲区容量&dwXfer, / 读取的字节数NULL) ; / 无重叠 I/O if (dwXfer = sizeof(nV
12、alue) ) std : cout “ read: ” nValue std : endl;nValue += nAdd;: SetFilePointer(hFile, 0, NULL, FILE_BEGIN) ; : WriteFile( hFile, / 要写入的文件reinterpret_cast (&nValue) , / 数据sizeof(nValue), / 缓冲区容量&dwXfer, / 写入的字节数NULL) ; / 无重叠 I/O if (dwXfer = sizeof(nValue) ) std : cout “write: ” nValue 0; -nTotal) HA
13、NDLE hThread = : CreateThread( NULL, / 缺省的安全性0, / 缺省的堆栈ThreadProc, / 线程函数reinterpret_cast (1) , / 增量0, / 无特殊的创建标志NULL) ; / 忽略线程 id : WaitForSingleObject(hThread, INFINITE) ; : Sleep(500) ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 5 页 - - - - - - - - - : C
14、loseHandle(hThread) ; hThread = INV ALID_HANDLE_VALUE; 运行结果(如果运行不成功,则可能的原因是什么?) :_ _ 阅读和分析程序,请回答问题:1) 程序中启动了多少个单独的读写线程?_ 2) 使用了哪个系统API 函数来创建线程例程?_ 3) 文件的读和写操作分别使用了哪个API 函数?_ _ 每次运行进程时,都可看到程序中的每个线程从前面的线程中读取数据并将数据增加,文件中的数值连续增加。这个示例是很简单的通讯机制。可将这一示例用作编写自己的文件读/写代码的模板。请注意程序中写入之前文件指针的重置。重置文件指针是必要的,因为该指针在读取
15、结束时将处于前四个字节之后,同一指针还要用于向文件写入数据。如果函数向该处写入新数值,则下次进程运行时,只能读到原来的数值。那么:4) 在程序中,重置文件指针使用了哪一个函数?_ 5) 从输出结果,对照分析程序,可以看出程序运行的流程吗?请简单描述:_ _ 第三部分用 pipe()创建一个管道文件,然后用fork() 创建两个生产进程和两个消费进程,它们之间通过pipe()传递消息。fork 系统调用pid=fork(); 创建一个子进程,子进程是父进程的完整复制,正常返回值为非负整数。对于父进程来说该数大于0,是子进程的编号(pid) ;对于子进程来说该数为零。正是利用返回值的不同可以决定二
16、者的后续动作。pipe 系统调用ret_val=pipe(fd); 参数定义为int fd2 。创建一个管道文件,返回两个文件描述符fd0 和 fd1 ,它们分别用于管道文件的读和写操作。管道文件创建后, 可以被 fork所创建的子进程共享。#include “sys/types.h”#include “sys/file.h”#include “unistd.h”char r_buf4; char w_buf4; int pipe_fd2; pid_t pid1,pid2,pid3,pid4; int producer(int id); int consumer(int id); int ma
17、in(int argc,char *argv) if(pipe(pipe_fd)0) printf( “pipe create error.n”); exit(-1); else printf( “pipe is created successfully!n”); if(pid1=fork()=0) producer(1); if(pid2=fork()=0) producer(2); if(pid3=fork()=0) consumer(1); if(pid4=fork()=0) consumer(2); close(pipe_fd0); close(pipe_fd1); int i,pid
18、,status; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 5 页 - - - - - - - - - for( i=0;i4;i+) pid=wait(&status); exit(0); int producer(int id) printf( “producer %d is running!n ”,id); close(pipe_fd0); int i=0; for(i=1;i10;i+) sleep(3); if(id=1) strcpy(w_buf, ”a
19、aa0”); else strcpy(w_buf,”bbb0”); if(write(pipe_fd1,w_buf,4)=-1) printf( “write to pipe errorn ”); close(pipe_fd1); printf( “producer %d is over!n ”,id); exit(id); int consumer(int id) close(pipe_fd1); printf( “consumer %d is running!n”,id); if(id=1) strcpy(w_buf, ”ccc0”); else strcpy(w_buf,”ddd0”);
20、 while(1) sleep(1); strcpy(r_buf, ”eee0”); if(read(pipe_fd0,r_buf,4)=0) break; printf( “Consumer %d get %s, while the w_buf is %sn ”, id,r_buf,w_buf); close(pipe_fd0); printf( “consumer %d is over!n”,id); exit(id); 先阅读和分析程序,写出运算结果,并加以解释:_ _ _ _ 四、实验总结请总结一下本次实验的收获、教训和感受, 结合课本内容谈一下你对进程间控制的理解。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 5 页 - - - - - - - - -