文件读写互斥

该文是2005年底在老东家开发监控程序时遇到的一个经典问题。回过头看来,竟然有同学(或者老师)看了该文,并给出了一条非常给力的评价,深感荣幸。

返回头看这篇文章,基本上给人一种凌乱的感觉,幸运的是没有多少人看过。作为对自己的反省,将该文重新整理结构,梳理结果。原文将作为历史文物保留。

 

问题提出:系统进程/线程对同一个文件的读写为互斥关系时,如何协调。本文将只针对于作者在在2005年参与开发的一个监控系统中,所遇到的典型情形给出分析以及解决方式。

 

问题详细描述:

该系统中,文件做为消息传送方式,典型的过程为:进程A写数据如文件X;进程B发现特定目录中有文件,名为X;B读取X中内容后删除X。X为带有时间戳的不重名文件。问题:A正在写文件时,B刚好被调度到发现并读取文件,此时数据可能未写入完整,造成1.数据不完整,2.文件删除操作可能失败等错误。项目中,文件X的内容非常短小,128bytes以内,一般情况下写入时间为毫秒级。

 

问题解决:

首先,不得不说,这是一个经典问题,刚刚搜索了一下,很多人有相同的问题并且在网上寻找着答案。本文只针对于当前系统有限背景下提出解决方案,并不适用于更多情景。

假定:A进程写文件过程中会一直保持对文件操作的排他性直到操作完成。【通过unix系统的IO机制,不是很懂,不进一步描述,待补充

 

解决方案中A进程不做任何变动,B进程为处理可能出现的访问问题。

B进程在发现某文件X存在于特定目录后,将通过探查probling的方式(使用fuser命令 : http://en.wikipedia.org/wiki/Fuser_%28Unix%29, unix lib中应该有相应的c native调用,本文不做调查,读者有兴趣请自行查阅相关手册)。如果该文件没有被其他进程使用,B进程将正常使用该文件,否则等待一小段时间后重新探测,直至文件未被占用。

 

回顾1:

2005年时,对可能的解决方案罗列了3点,但是不外乎两种情况

1. 同一进程的不同线程对同一文件处理。(此问题将排除在本文讨论之列,因为一般情况下进程内部比较容易协调处理)

2. 不同进程对同一文件处理。(本文只特定处理上述问题详细描述中的情况,更一般的情况,需要另行总结,例如,两个进程可能多次处理同一个文件,等等)。

 

回顾2:

之前提出的通过使用新的文件或者文件名称作为互斥使用文件的signal方式,由于无法保证其原子性,所以实际情况下可能会出现问题,务必不要使用。

 

扩展:unix系统中,fcntl, flock, lockf函数用于用于文件锁是非常有用的. 参考unix环境高级高级编程 v2 CH P358.

其中flock是对整个文件加锁。

对于数据库系统,要求针对文件的某个部分加锁,参考书中的相关章节

 

下文为2005年底所著,为了见证当时的情形以自勉,特保留。

开发中,可能会出现 某个程序读某个文件的时候,令一个程序在写该文件,造成问题.


解决办法:

1 如果两个程序是同属于一个classloader的两个线程,那么使用一个文件管理的类来统一管理对文件的读写,避免资源冲突问题发生

2如果两个程序是两个独立的进程,那么,暂时没什么办法

  目前采用的是 读文件之前等一秒,因为文件一般比较小,一秒以内的时间肯定已经写完了

3 如果两个程序是两个独立的进程,可以以某种形式设定一个信号量

  而不是通过直接查看目录下时候有文件来判断是否进行读写


---------------------------------------------------------------

开发中,可能会出现 某个程序读某个文件的时候,令一个程序在写该文件,造成问题

解决办法:
使用互斥锁

1 如果两个程序是同属于一个classloader的两个线程,[即,两个程序属于同一个进程]
  那么使用一个文件管理的类来统一管理对文件的读写,避免资源冲突问题发生
 
  问题:在同一个进程中使用两个线程的方式是否会减小执行的效率。一般unix cpu都是按
  时间片来分配进程执行时间的。
 
2如果两个程序是两个独立的进程,那么,暂时没什么办法
  目前采用的是 读文件之前等一秒,因为文件一般比较小,一秒以内的时间肯定已经写完了
 
3 如果两个程序是两个独立的进程,可以以某种形式设定一个信号量
  而不是通过直接查看目录下时候有文件来判断是否进行读写
  下面给出两个具体方法:
  方法1:以新建一个文件的名称作为信号量
     场景:对文件file_x进行读写操作,两个进程p_read, p_write对该文件进行读写
     正常情况时进程p_write对文件写完后,p_read读取该文件内容
     信号量:设定一个新文件,名称为file_x_0/1,如果file_x_0就表示文件已经写完
             file_x_1表示文件正在写,请等待,不要读
     对信号量的控制:通过第三个进程进行管理
             前提:保证对信号量的修改是原子操作
     问题:如果有成千个文件短时间内处理,需要设定信号量,这种方法,会造成系统磁盘[]创建管理文件
     的操作过于频繁,[影响系统性能]
  方法2:以待读写的文件的名称增加参数为信号量
        各进程在占用某文件之前,先判断是否已经被占用[根据文件名称]
        如果没有占用,先将文件名称改为自己的名称,表明自己已经占用该文件
        处理后,将文件名称改回无人占用的名称。
        前提:修改文件名称操作为原子操作。

-------------

已 解决

使用unix的一个命令 fread[好像是这个],可以判定指定文件是否有进程在读写!!

你可能感兴趣的:(小总结,SOA,Related)