os实验指导书(新)1(2) 下载本文

1、实验目的

1) 回顾系统进程、线程的有关概念,加深对Windows 2000线程的理解。

2) 了解互斥体对象,通过对生产者消费者等进程间同步与互斥经典算法的实现,加深对P、V原语以及利用P、V原语进行进程间同步与互斥操作的理解。

2、实验内容和步骤

(1). 生产者消费者问题

步骤1:创建一个“Win32 Consol Application”工程,然后拷贝清单3-1中的程序,编译成可执行文件。 步骤2:在“命令提示符”窗口运行步骤1中生成的可执行文件。运行结果: 范例:E:\\课程\\os课\\os实验\\程序\\os11\\debug>os31 (假设编译生成的可执行文件是os31.exe)

__

步骤3:仔细阅读源程序,找出创建线程的WINDOWS API函数,回答下列问题:线程的第一个执行函数是什么(从哪里开始执行)?它位于创建线程的API函数的第几个参数中? DWORD WINAPI Producer(LPVOID lpPara) 第三个参数

hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);___________________________________ 步骤4:修改清单3-1中的程序,调整生产者线程和消费者线程的个数,使得消费者数目大与生产者,看看结果有何不同。运行结果:

const unsigned short PRODUCERS_COUNT = 3; //生产者的个数 const unsigned short CONSUMERS_COUNT = 6; //消费者的个数

21

_______

___________________________________________________________________________________________________________________________________________________________________________________________________________________________________ 从中你可以得出什么结论:

_____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

步骤5:修改清单3-1中的程序,按程序注释中的说明修改信号量EmptySemaphore的初始化方法,看看结果有何不同。运行结果:

EmptySemaphore=CreateSemaphore(NULL,SIZE_OF_BUFFER,SIZE_OF_BUFFER,NULL);_改为 EmptySemaphore=CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);_

无法执行

___________________________________________________________________________________________________

22

步骤6:根据步骤4的结果,并查看MSDN,回答下列问题 1)CreateMutex中有几个参数,各代表什么含义。

_____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

2)CreateSemaphore中有几个参数,各代表什么含义,信号量的初值在第几个参数中。

_____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

3)程序中P、V原语所对应的实际Windows API函数是什么,写出这几条语句。 WaitForSingleObject(EmptySemaphore,INFINITE); P操作 WaitForSingleObject(Mutex,INFINITE); ReleaseMutex(Mutex); V操作

ReleaseSemaphore(FullSemaphore,1,NULL);

4)CreateMutex能用CreateSemaphore替代吗?尝试修改程序3-1,将信号量Mutex完全用CreateSemaphore及相关函数实现。写出要修改的语句:

_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

(2). 读者写者问题

根据实验(1)中所熟悉的P、V原语对应的实际Windows API函数,并参考教材中读者、写者问题的算法原理,尝试利用Windows API函数实现第一类读者写者问题(读者优先)。

3、 实验结论

__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

4、 程序清单

清单3-1 生产者消费者问题 #include #include

const unsigned short SIZE_OF_BUFFER = 2; //缓冲区长度 unsigned short ProductID = 0; //产品号

unsigned short ConsumeID = 0; //将被消耗的产品号

unsigned short in = 0; //产品进缓冲区时的缓冲区下标 unsigned short out = 0; //产品出缓冲区时的缓冲区下标

23

int buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列 bool p_ccontinue = true; //控制程序结束 HANDLE Mutex; //用于线程间的互斥

HANDLE FullSemaphore; //当缓冲区满时迫使生产者等待 HANDLE EmptySemaphore; //当缓冲区空时迫使消费者等待

DWORD WINAPI Producer(LPVOID); //生产者线程 DWORD WINAPI Consumer(LPVOID); //消费者线程

int main() {

//创建各个互斥信号

//注意,互斥信号量和同步信号量的定义方法不同,互斥信号量调用的是CreateMutex函数,同步信号量 //调用的是CreateSemaphore函数,函数的返回值都是句柄。 Mutex = CreateMutex(NULL,FALSE,NULL);

EmptySemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER,SIZE_OF_BUFFER,NULL); //将上句做如下修改,看看结果会怎样

//EmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL); FullSemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER,NULL);

//调整下面的数值,可以发现,当生产者个数多于消费者个数时, //生产速度快,生产者经常等待消费者;反之,消费者经常等待 const unsigned short PRODUCERS_COUNT = 3; //生产者的个数 const unsigned short CONSUMERS_COUNT = 1; //消费者的个数

//总的线程数

const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;

HANDLE hThreads[THREADS_COUNT]; //各线程的handle

DWORD producerID[PRODUCERS_COUNT]; //生产者线程的标识符 DWORD consumerID[CONSUMERS_COUNT]; //消费者线程的标识符

//创建生产者线程

for (int i=0;i

hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]); if (hThreads[i]==NULL) return -1; }

//创建消费者线程

for (i=0;i

hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]); if (hThreads[i]==NULL) return -1; }

while(p_ccontinue){

if(getchar()){ //按回车后终止程序运行 p_ccontinue = false; } }

24

return 0; }

//生产一个产品。简单模拟了一下,仅输出新产品的ID号 void Produce() {

std::cout << std::endl<< \ std::cout << \}

//把新生产的产品放入缓冲区 void Append() {

std::cerr << \ buffer[in] = ProductID; in = (in+1)%SIZE_OF_BUFFER;

std::cerr << \

//输出缓冲区当前的状态

for (int i=0;i

//从缓冲区中取出一个产品 void Take() {

std::cerr << \ ConsumeID = buffer[out]; buffer[out] = 0;

out = (out+1)%SIZE_OF_BUFFER;

std::cerr << \

//输出缓冲区当前的状态

for (int i=0;i

//消耗一个产品 void Consume()

25