现在的位置: 首页 > 综合 > 正文

使用FIFO实现POSIX有名信号量

2013年03月05日 ⁄ 综合 ⁄ 共 1055字 ⁄ 字号 评论关闭

使用FIFO实现POSIX信号量算是一个《UNIX网络编程 卷二》中第十章的一个高级内容,其实数中仅仅是大致的实现了POSIX信号量中极为有限的一部分功能。书中重新写了sem_open函数、sem_unlink函数、sem_close函数、sem_wait函数和sem_post函数,为什么说使用FIFO仅仅实现了POSIX信号量中极为有限的一部分呢?我们需要从FIFO开始分析,分析完FIFO的性质之后这些问题就不难理解了。

首先FIFO是一个有名的半双工管道,这种有名管道的实现类似于队列,我们可以在其一端执行写入操作,另一端进行读取操作。虽然FIFO是UNIX系统中可以看得到的文件,但是要清楚向FIFO中读写数据并不需要经过磁盘IO,实际上数据仍然是写到内存中的。我们可以猜测一下FIFO的实现,既然IPC的一个设计要求就是高性能,而且FIFO是伴随进程持续的,那么为什么不把其映射到内中呢?在这里我们遇到了第一个问题,就是FIFO的持续性的问题,可知当最后一个进程(线程)关闭了FIFO时,FIFO中的数据将会被丢弃。想一想POSIX信号量,信号量是一个(至少)伴随内核持续的一种IPC。书中给出的思路是每次挂出信号量时向FIFO中写入一个字符,等待时从FIFO总读出一个字节。可以预见下面的问题,当第一个进程调用了我们实现的sem函数时,对于这个进程而言是没有什么影响的,当这个进程结束之后,另一个进程试图用sem_open函数打开信号量时貌似也没有什么问题,接下来我们调用sem_wait函数时就会发现进程在此处阻塞,原因就是当FIFO没有进程打开时里面的数据会被丢弃。这个问题需要我们特别的注意,下面还有一个问题是因为FIFO自身性质导致的。

当我们实现一个POSIX信号量时要注意了,使用open函数如果不指定不阻塞的话,那么进程或者线程会阻塞在open函数处,当我们不考虑实现sem_trywait时,我们需要用非阻塞的模式分别以读和写的模式打开FIFO,之后还需要关闭在读描述符上的非阻塞标记。其实在sem_open函数实现的过程中要注意的东西有很多,实现的大部分难度都集中在这里,我们不得不对不同的情况作出不同的处理,包括出错时要关闭打开的所有文件描述符并释放内存等。我们不能让函数返回一段静态内存,这样是不安全的。

接下来的问题就和FIFO没有多大的关系了,一个有关信号量是否有效的校验问题,当然书上给出的方法并不完美,在运行的时候很容易就导致程序的崩溃。不过这个检查又总是要比没有好一些吧。

抱歉!评论已关闭.