哈工大李治军老师操作系统实验之信号量实现和应用

该博客详细介绍了在Ubuntu环境下,如何使用信号量解决生产者-消费者问题,包括在Linux 0.11内核中实现信号量的系统调用过程。通过分析程序设计,解释了信号量在进程同步和互斥中的作用,以及如何利用‘哨兵’技巧来模拟清除操作。实验步骤包括添加系统调用、修改内核源代码、编译内核以及在Linux 0.11中运行测试程序。
摘要由CSDN通过智能技术生成

实验目的

  1. 加深对进程同步与互斥概念的认识
  2. 掌握信号量的使用,应用它解决 生产者–消费者问题
  3. 掌握信号量的实现原理

实验内容

  1. 在Ubuntu下编写程序,用信号量解决生产者-消费者问题
  2. 在0.11中实现信号量,用生产者-消费者程序(1)检验

在Ubuntu下编写测试程序

  • 程序要求

    生产者往文件中写入数字从0开始到最大为500,消费者从文件当中读取数字并更新文件,同时消费者向终端输出:进程ID : 读取的数字

    缓冲区最大10个数字。

  • 分析

    做信号量相关的程序需要分析哪里需要设置信号量,以及设置什么信号量。文件为空需要通知生产者写入数字,当文件为满,需要通知消费者赶快取走数据,当缓冲区数据不为空也不为满呢?这就是需要做互斥了。当生产者拿到锁进入缓冲区发现缓冲区为满那么就直接退出,或消费者拿到锁发现缓冲区为空那么也直接退出去。

  • 程序设计

    /**
     * 一个生产者+多个消费者,共享区为文件,这个文件最大存储10个数,消费者拿走一个数据的同时需要清除缓冲区数据并在终端以:
     * 进程ID+数字形式显示出来。 
     *显然,这里存在两种同步机制:互斥+资源共享。任何时刻只能有一个进程访问资源,当资源满或空需要进行资源控制 
     **/
    #include <unistd.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <semaphore.h>
    #include <stdio.h>
    #include <sys/wait.h>
    /**
     * @brief  使用的信号量操作函数如下:1. sem_open()建立信号量;  2. sem_close()关闭信号量; 3. sem_wait()信号量-1; 4. sem_post()信号量+1
     * @note   
     * @param   
     * @param  
     * @retval 
     */
    int COUNTER =4;
    int main(int argc, char const *argv[])
    {
         
        pid_t writer,reader[COUNTER];//writer生产者, reader消费者
        int fp = open("file", O_CREAT | O_RDWR | O_TRUNC, 0666);
        int  count=0;  //记录当前共享区的数字个数
        //创建信号量
        sem_t* full=sem_open("/full",O_CREAT,0666,0);
        sem_t* empty=sem_open("/empty",O_CREAT,0666,10);
        sem_t* mutex=sem_open("/mutex",O_CREAT,0666,1);
        
        
        int tmp=0,position=0;
        for(int i=0;i<COUNTER;i++)//消费者进程
        {
         
           pid_t cur_pid=fork();
          if(cur_pid<0)
          {
         
              printf("fork :[%d]   error\n",i);
              return 0;
          }
          else if(cur_pid==0)
          {
         
            while(1)
            {
         
              sem_wait(full);
              sem_wait(mutex);
              //检查是否达到缓冲区大小
              lseek(fp,0,SEEK_SET);
              read(fp,&tmp,sizeof(int));
              if(tmp==500)  //达到极限
              {
         
                  sem_post(mutex);
                  sem_post(full);
                  break;
              }
              //如果没达到就读取
              position=(tmp+1)%500+1;
              lseek(fp,position*sizeof(int),SEEK_SET);
              read(fp,&tmp,sizeof(int));
              printf("%d : %d\n",getpid(),tmp);
              fflush(stdout);
              //将本次读取的数据写入标志位(数组下标为0的位置 )
              lseek(fp,0,SEEK_SET);
              write(fp,(void *)&tmp,sizeof(int));
              //释放信号量
              sem_post(mutex);
              sem_post(empty);
            }
            return 0;
          }
        }
        /**
         * @brief  在生产者进程加入数据时需要更新标志位,
         * @note   
         * @retval None
         */
        for(int i=0;i<500+COUNTER+1;i++)
        {
         
            sem_wait(empty);
            sem_wait(mutex);
            position=(i%500)+1
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值