您好,欢迎访问三七文档
实验报告/*学号:姓名:/*实验序号:1*//*实验名称:用信号量来实现读者写者问题(写者优先)*//*实验目的:理解进程(或线程)及信号量的概念*//*实验当堂所要完成的事情列表*///―――――――――――――1/10/*1.上网查找有关API函数,例如句柄,创建进程的函数,以及这些函数的对应参数都有哪些,这些参数有什么作用等。例如:WaitForSingleObject(),CreateSemaphore()等。2.对与实验有关的知识进行查看,例如查看有关参考书,和上课用的PPT等,深入了解这些原理,例如用信号量来实现进程之间的互斥,以及落实到具体的代码实现应该怎么组织数据结构,用哪些具体的API函数,函数之间的传参应该怎么办等。3.根据预习报告,虽有借鉴之嫌,但是还是可以启发一下程序的具体结构,将程序执行的结构图画出来。*//*源代码(必须含注释,要求规范性)及程序流程图*///―――――――3/10…..…..…..//写者优先.cpp:定义控制台应用程序的入口点。//#includewindows.h#includeconio.h#includestdlib.h#includeio.h#includestring.h#includestdio.hHANDLEmutex;HANDLEbuffer;voidreader(void){intrc=0;while(TRUE){WaitForSingleObject(&mutex,-1);//P原语API函数rc=rc+1;if(rc==1)//如果这是第一个读者WaitForSingleObject(&buffer,-1);ReleaseSemaphore(&mutex,1,NULL);//V原语API函数//ReleaseSemaphore(&buffer,1,NULL);WaitForSingleObject(&mutex,-1);printf(释放对buffer的互斥访问\n);//printf(读者访问read_data_base\n);//printf(读者准备读\n);printf(读者开始读缓冲区中数据...\n);//读者读printf(读者开始开始退出缓冲区...\n);rc=rc-1;if(rc==0)ReleaseSemaphore(&buffer,1,NULL);//printf(开始读use_data_read\n);}}voidwriter(){while(TRUE){//think_up_data();WaitForSingleObject(&buffer,-1);//write_data_base();//在此可以更新数据//printf(写者写\n);printf(写者准备写\n);printf(写者开始往缓冲区中写数据...\n);//写者写printf(写者开始退出缓冲区...\n);ReleaseSemaphore(&buffer,1,NULL);printf(写者释放对buffer的互斥访问\n);}}voidmain(){HANDLEData[2];//创建HANDLE数组Datamutex=CreateSemaphore(NULL,1,1,NULL);//创建互斥信号量buffer=CreateSemaphore(NULL,1,1,NULL);HANDLEhandle[2];//创建HANDLE数组handle//以下是创建生产着和读者进程handle[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(writer),&Data[0],0,NULL);if(handle[0]==NULL)printf(创建写者线程失败\n);handle[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(reader),&Data[1],0,NULL);if(handle[1]==NULL)printf(创建读者线程失败\n);system(pause);}/*程序流程图:有无读写唤醒等待的写线程*//*编译过程中出现的问题及其相应解决:1.头文件问题解决:所有的函数直接调用需要用到头文件,API函数需要用windows.h,其他头文件虽然没有用,但是为了保证不出错还是加上了。2.API函数的参数问题解决:API函数是系统一级的函数,,有些函数的调用需要用到很多的参数,参数不同会导致结果的不同,例如:CreateSemaphore(NULL,1,1,NULL),这个函数需要四个参数,第一个参数和第四个参数在程序中没有用到,所以可以设置为NULL,第三个参数是可以设置读/写等待所有读线程完成再执行申请资源,进行读操作已有进程对buffer进行读写?读/写?所有读线程处理完毕,释放互斥信号量开始判断是否有读者或写者进入信号量的最大计数,第二个参数是设置信号量的初值是多少。如果程序有些问题实在解决不了的话,可以修改参数试一下函数是否有会让程序正常。3.函数的调用问题解决:API函数和普通函数其实本质上都是一样的,但是进程和普通的变量不一样。例如P-V原语,这对函数必须是成对出现的,否则没有意义。但是在API函数中并没有P函数和V函数,需要自己查找或者上网搜索。还有函数的嵌套调用,例如:CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(reader),&Data[1],0,NULL),这个函数是我直接利用了别人的代码,调用了reader函数,但是前面的那个参数至今未明白,上网看了一下,说是强制转换。*//*运行过程中出现的问题及其相应解决:1.读写信号量的不互斥解决:在刚写好程序的时候,发现读者和写者程序同时调用,表现为交叉打印,所以用了程序逐句执行,逐句执行到最后,出现了汇编代码,只好不了了之。后来经过仔细观察之后才发现可能是函数的参数有问题,修改了参数之后,程序变得正常了。2.每个读者一来都要判断是否有数据可读,但是当第一个读者已经拿到数据缓存区的使用权时,接下来的读者便无法对数据进行读操作;而同时有写者等待的情况下,一旦第一个读者读完后,写者便只能写,写完读者才能读解决:这是由于同步信号量导致的结果。对于同一个缓冲区,只能实现读者读,然后写者写,又读者读,写者写,所以便不能实现若干个读者同时进行读操作。只需调整为当第一个读者来的时候拿到读数据的使用权后,直到没有读者等待后,再交出缓冲区的使用权,再让写者写即可解决此问题。3.运行过程中会出现直接跳出的现象解决:是运行环境的问题,如果是VS2012会在程序运行完之后直接跳转退出,可以加入System(“pause”)暂停语句是程序停止。*///―――――――――――――――――――――――――――――――3/10/*实验总结―――――――――――――――――――――――――――3/10这是第一次对API函数的应用,发现API函数虽然名字很长,但是认真去做还是比较好做出来,毕竟函数是死的,只要参数满足,就可以调用,而不用自己编写,这是操作系统提供的接口,可以对进行系统级的编程,对程序的进一步开发有很大的帮助。API函数很多,需要仔细的查询,所以只要用心慢慢去做就可以了。多进程或多线程的读者写者程序比较复杂,所以只有自己利用API函数写了一个单线程的程序。自己也看了很多多线程的程序,是给互斥的进程加上了循环,但是一加上循环,程序考虑的点就会变的更多,考虑到自己可以将程序弄的更加明白,所以我还是选择了单线程的编写。程序中,读者和写者共享同一个资源缓冲区。需要对各个线程的操作进行一定的互斥,防止多个线程在并发执行的过程中,发生死锁现象。但是考虑到单线程,没有并发,但是资源共享了,就是分配一个资源,所以程序才会容易很多。写操作系统的实验需要参考很多的书,只有见识的够多才能写出代码,所以duoduyixie书,比如参考书等很有必要。运行截图:*/
本文标题:写者优先实验报告
链接地址:https://www.777doc.com/doc-2632818 .html