操作系统NACHOS实验(三)使用信号量解决生产者/消费者同步问题

匿名 (未验证) 提交于 2019-12-02 23:03:14

操作系统NACHOS实验(三)使用信号量解决生产者/消费者同步问题

实验思路

Lab3文件夹中已经给出了本次实验需要使用的一些类定义,比如环形缓冲区Ring类等,我们所要完成的就是在prodcons++.cc中补充相关代码。
首先需要完善信号量的初始化

mutex=new Semaphore("mutex",1); nempty=new Semaphore("nempty",BUFF_SIZE); nfull=new Semaphore("nfull",0); 

接下来就是定义临界区,对于临界区的定义要注意各个信号量操作的顺序。

关键源代码注释以及程序说明

prodcons++.cc代码

…… //添加的头文件 #include <fcntl.h> #include <stdlib.h> #include <unistd.h>  …… void Producer(_int which) {     int num;     slot *message = new slot(0,0);  //  This loop is to generate N_MESSG messages to put into to ring buffer //   by calling  ring->Put(message). Each message carries a message id  //   which is represened by integer "num". This message id should be put  //   into "value" field of the slot. It should also carry the id  //   of the producer thread to be stored in "thread_id" field so that  //   consumer threads can know which producer generates the message later //   on. You need to put synchronization code //   before and after the call ring->Put(message). See the algorithms in //   page 182 of the textbook.      for (num = 0; num < N_MESSG ; num++) {       // Put the code to prepare the message here.       // ...              message->value=num; 	  message->thread_id=which; 	       // Put the code for synchronization before  ring->Put(message) here.       // ...              nempty->P();//空槽信号量减       mutex->P();//互斥信号量 	         ring->Put(message);        // Put the code for synchronization after  ring->Put(message) here.       // ...                     mutex->V();//释放互斥信号量       nfull->V();//满槽信号量加    } }  //---------------------------------------------------------------------- // Consumer // 	endless loop to fetch messages from the ring buffer and  //      record these message in the corresponding file. //       //----------------------------------------------------------------------  void Consumer(_int which) {     char str[MAXLEN];     char fname[LINELEN];     int fd;          slot *message = new slot(0,0);      // to form a output file name for this consumer thread.     // all the messages received by this consumer will be recorded in      // this file.     sprintf(fname, "tmp_%d", which);      // create a file. Note that this is a UNIX system call.     if ( (fd = creat(fname, 0600) ) == -1)      { 	perror("creat: file create failed"); 	exit(1);     }          for (; ; ) {        // Put the code for synchronization before ring->Get(message) here.       // ...       nfull->P();//满槽信号量减       mutex->P();//互斥信号量阻塞              ring->Get(message);        // Put the code for synchronization after ring->Get(message) here.       // ...              mutex->V();//释放       nempty->V();//空槽信号量加       // form a string to record the message       sprintf(str,"producer id --> %d; Message number --> %d;\n",  		message->thread_id, 		message->value);       // write this string into the output file of this consumer.        // note that this is another UNIX system call.       if ( write(fd, str, strlen(str)) == -1 ) { 	    perror("write: write failed"); 	    exit(1); 	  }     } }    //---------------------------------------------------------------------- // ProdCons // 	Set up semaphores for shared round buffer and  //	create and fork producers and consumer threads //----------------------------------------------------------------------  void ProdCons() {     int i;     DEBUG('t', "Entering ProdCons");      // Put the code to construct all the semaphores here.     // .... 	mutex=new Semaphore("mutex",1); 	nempty=new Semaphore("nempty",BUFF_SIZE); 	nfull=new Semaphore("nfull",0);     // Put the code to construct a ring buffer object with size      //BUFF_SIZE here.     // ...         ring=new Ring(BUFF_SIZE);       // create and fork N_PROD of producer threads      for (i=0; i < N_PROD; i++)      {       // this statemet is to form a string to be used as the name for        // produder i.        sprintf(prod_names[i], "producer_%d", i);        // Put the code to create and fork a new producer thread using       //     the name in prod_names[i] and        //     integer i as the argument of function "Producer"       //  ...       producers[i]=new Thread(prod_names[i]); 	  producers[i]->Fork(Producer, i);      };      // create and fork N_CONS of consumer threads      for (i=0; i < N_CONS; i++)      {       // this statemet is to form a string to be used as the name for        // consumer i.        sprintf(cons_names[i], "consumer_%d", i);       // Put the code to create and fork a new consumer thread using       //     the name in cons_names[i] and        //     integer i as the argument of function "Consumer"       //  ...       consumers[i]=new Thread(cons_names[i]); 	  consumers[i]->Fork(Consumer,i);      }; } 

调试记录


第一次make报错,原因是引用成员变量使用了点而不是箭头。

修改代码后,执行依旧报错,但错误是creat函数未定义。在代码中,creat函数是UNIX的系统调用。随后添加了#include <fcntl.h>#include <stdlib.h>#include <unistd.h> 三个头文件,问题解决。
一开始总是只有temp_1中有数据,在查看main.cc后发现命令

-rs causes Yield to occur at random (but repeatable) spots

,给予其一定值,输出如下:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!