信号量在linux0.11下的实现及其在生产者,消费者应用中的体现

此为Mr.Peach在哈工大做的第四次操作系统,想说说思路与注意细节及信号量的更多相关内容,之后可能用ruby重写一份代码以帮助理解。(本文假定你为工大学生,对信号量与进程同步互斥,系统调用有一定了解)


首先说说生产者,消费者模型的工作流程。在每一项要求后面,我想放上解决思路,而不是源码,sunner设计这么一个实验不容易。

  • 建立一个生产者,N个消费者,N>1。用文件实现一个共享缓冲区。
子进程会继承父进程拥有的大多数资源,包括父进程打开的文件。而生产者唯一,消费者众多。于是容易想到生产者即是父进程,消费者是一个个派生出的子进程。子进程使用父进程的文件资源。
  • 生产者进程依次向缓冲区写入整数0.1.2.....M, M>=500。

注意到依次二字,我们知道,生产的整数资源是随着消耗的进行递增的。这就要求我们记录生产者的生产进度。也就是在进程同步的过程中,实时的生产数字。而生产者需生产M次。可以用for(i=0; i<M; i++){ ...  }来实现,递增的 i 即可记录生产到的数字,循环M次即可实现生产M次的要求。  { ... } 即代表生产过程。

  • 消费者从缓冲区读书,每次读一个,并将读出的数字从缓冲区删除,然后输出进程id以及数字
  • 缓冲区最多保存10个数
由于是有限缓冲,容易得知,需要3个信号量 empty,full,mutex。其中mutex的value置1,提供了对缓冲池访问的互斥要求,empty置10,说明初始缓冲池内空资源数目是10,full置0,即可利用资源数是0。
可以知道,生产者与消费者进程独占缓冲区访问的上限周期均是10。


有几个tips可以注意:
  • 各个消费者读取资源数目的总和应与生产者生产的整合M相等。可以这么控制:
当创建每个消费者子进程时,为其生成一个常量a。之后在消费者的历程中放入循环 while(i++< a),i初值为0。循环中进行消费者的取数行为。这样即可保证该消费者只能取到a个资源。各消费者常量和为M
  • 控制缓冲资源上限
缓冲资源文件我认为合理的设计方式是,永远只存10个数。10个数中,部分为可取用的整数资源,部分为不可用的高阻状态(最近做硬件实验做得蛋疼,就让我用高阻来代替不可用的意思吧。。T.T)。当消费者要取数时,打开该文件,从头开始遍历其资源,将第一个可用的数取走,并在该位置填上高阻状态,重新写入缓冲文件,同时更新full的value。当生产者要造数时,遍历资源,将第一个可用资源开始的所有资源挪到前方,再在其后加上生产到的资源 i 。这样整理后前半部均为可用数,后半部为高阻,同时更新empty的value。
  • 为方便Miumiu同学写os,下面几个文件读写函数顺便提一下。
缓冲资源文件适合用系统调用写,因为不设计格式问题,只与容量有关。
int file;//声明文件描述符
file = open("buffer", O_RDWR | O_CREAT, 00644);//若存在,就以可读写模式打开,不存在则创建并打开
lseek(file,0L,SEEK_SET);//将文件读取指针指向文件头,偏移0个字节。
read(file, temp, sizeof(int)*10);//将文件中文件读取指针后的10*4个字节数放入temp。
write(file,temp,sizeof(int)*10);//将temp的内容写入文件指针指向的文件区域。
close(file);//关闭文件

FILE *log;
log = fopen("pc.log", "a+");以a+方式打开当前目录下的pc.log文件,若无则创建,若有则在文件末尾续写
fprintf(log, "%d\t%d\n", getpid(), temp[i]);按标准输出格式在文件末写入进程号与消费的资源
fclose(log);

在linux 0.11下实现信号量可以用其内部的锁机制。
  • sem_t *sem_open(const char* name, unsigned int value)的逻辑:
对于内核区域,我们可以定义一个信号节点的数组,限定内核中只能有规定限额的信号量。
每个信号量有其名name,值value,及wait的进程pid。
open时,在可用信号中寻找相同的name的信号,若有,返回。若无,则创建信号,并赋value。这很简单
  • wait与post
此两项操作,即先关中断,相应历程,开中断。针对wait,若其value小于1,则sleep_on其对应的进程。若value大于1,则减之。这里说下,sleep_on中睡眠的进程队列是以隐式链表实现的,不需手工操作。因此sem.c中也不需建一个等待进程的队列。 针对post,其value加1,wake_up其对应进程即可。也很简单。
  • unlink
在可用信号中寻找相同name的信号,将其标记为不可用即可,连名字都不用删。


啊哈。。我决定以后按照这种方式写os的参考,发思路比发代码有节操多了。。要发源码也要发ruby的,因为它不可用。嘿嘿。。
By the way。。推荐一下new soul。。最近真的很喜欢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值