操作系统实验二.doc_第1页
操作系统实验二.doc_第2页
操作系统实验二.doc_第3页
操作系统实验二.doc_第4页
操作系统实验二.doc_第5页
全文预览已结束

VIP免费下载

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

实验二 并发与调度一、 实验目的在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000线程同步的理解。通过分析实验程序,了解管理事件对象的API。了解在进程中如何使用事件对象,在进程中如何使用互斥体对象,线程如何通过文件映射对象发送数据。在Linux Redhat 9.0操作系统平台上,用pipe()创建一个管道文件,然后用fork()创建两个生产进程和两个消费进程,它们之间通过pipe()传递消息。二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Windows 2000 Professional,Linux Redhat 9.0操作系统平台,Visual C+ 6.0企业版。三、实验内容和步骤第一部分:互斥体对象本程序中显示的类CCountUpDown使用了一个互斥体来保证对两个线程间单一数值的访问。每个线程都企图获得控制权来改变该数值,然后将该数值写入输出流中。创建者实际上创建的是互斥体对象,计数方法执行等待并释放,为的是共同使用互斥体所需的资源 (因而也就是共享资源) 。利用互斥体保护共享资源 / mutex项目 # include # include class CCountUpDown public: CCountUpDown(int nAccesses) : m_hThreadInc(INVALID_HANDLE_VALUE) , m_hThreadDec(INVALID_HANDLE_VALUE) , m_hMutexValue(INVALID_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, DecThreadProc, reinterpret_cast (this) , 0, NULL) ; : ReleaseMutex(m_hMutexValue) ; virtual CCountUpDown() : CloseHandle(m_hThreadInc) ; : CloseHandle(m_hThreadDec) ; : CloseHandle(m_hMutexValue) ; virtual 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_hMutexValue, 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 (lpParam) ; 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() CCountUpDown ud(50) ; ud.WaitForCompletion() ; 分析程序的运行结果,可以看到线程 (加和减线程) 的交替执行 (因为Sleep() API允许Windows切换线程) 。在每次运行之后,数值应该返回初始值 (0) ,因为在每次运行之后写入线程在等待队列中变成最后一个,内核保证它在其他线程工作时不会再运行。1) 请描述运行结果 (如果运行不成功,则可能的原因是什么?) :_2) 根据运行输出结果,对照分析程序,可以看出程序运行的流程吗?请简单描述: _第二部分 线程通过文件对象发送数据 Windows 2000提供的线程间通讯类内核对象允许同一进程或跨进程的线程之间互相发送信息,包括文件、文件映射、邮件位和命名管道等,其中最常用的是文件和文件映射。这类对象允许一个线程很容易地向同一进程或其他进程中的另一线程发送信息。演示线程通过文件对象发送数据 # include # include static LPCTSTR g_szFileName = “w2kdg.Fileobj.file.data.txt” ; static DWORD WINAPI ThreadProc (LPVOID lpParam) LONG nAdd = reinterpret_cast (lpParam) ; TCHAR szFullName MAX_PATH ; : GetTempPath(MAX_PATH, szFullName) ;/ 取得路径 : strcat(szFullName, g_szFileName) ; HANDLE hFile = : CreateFile( szFullName,/ 文件的完全名称 GENERIC_READ | GENERIC_WRITE,/ 具有所有的访问权 FILE_SHARE_READ,/ 允许其他线程读取 NULL,/ 缺省的安全性 OPEN_ALWAYS,/ 创建或打开文件 FILE_ATTRIBUTE_NORMAL,/ 普通文件 NULL) ;/ 无模板文件 if (hFile != INVALID_HANDLE_VALUE) LONG nValue(0) ; DWORD dwXfer(0) ; : ReadFile( hFile,/ 要读取的文件 reinterpret_cast (&nValue) ,/ 缓冲区 sizeof(nValue) ,/ 缓冲区容量 &dwXfer,/ 读取的字节数 NULL) ;/ 无重叠I/O if (dwXfer = sizeof(nValue) ) 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) HANDLE hThread = : CreateThread( NULL,/ 缺省的安全性 0, / 缺省的堆栈 ThreadProc,/ 线程函数 reinterpret_cast (1) ,/ 增量 0,/ 无特殊的创建标志NULL) ;/ 忽略线程id: WaitForSingleObject(hThread, INFINITE) ; : Sleep(500) ; : CloseHandle(hThread) ; hThread = INVALID_HANDLE_VALUE;运行结果 (如果运行不成功,则可能的原因是什么?) :_阅读和分析程序,请回答问题:1) 程序中启动了多少个单独的读写线程? _2) 使用了哪个系统API函数来创建线程例程?_3) 文件的读和写操作分别使用了哪个API函数? _每次运行进程时,都可看到程序中的每个线程从前面的线程中读取数据并将数据增加,文件中的数值连续增加。这个示例是很简单的通讯机制。可将这一示例用作编写自己的文件读/写代码的模板。请注意程序中写入之前文件指针的重置。重置文件指针是必要的,因为该指针在读取结束时将处于前四个字节之后,同一指针还要用于向文件写入数据。如果函数向该处写入新数值,则下次进程运行时,只能读到原来的数值。那么:4) 在程序中,重置文件指针使用了哪一个函数? _5) 从输出结果,对照分析程序,可以看出程序运行的流程吗?请简单描述: _第三部分 用pipe()创建一个管道文件,然后用fork()创建两个生产进程和两个消费进程,它们之间通过pipe()传递消息。fork系统调用 pid=fork();创建一个子进程,子进程是父进程的完整复制,正常返回值为非负整数。对于父进程来说该数大于0,是子进程的编号(pid);对于子进程来说该数为零。正是利用返回值的不同可以决定二者的后续动作。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 main(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,status;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,”aaa0”);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”);while

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论