1. 程式人生 > >[原]檔案讀寫互斥

[原]檔案讀寫互斥

該文是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[好像是這個],可以判定指定檔案是否有程序在讀寫!!


FROM: http://m.blog.csdn.net/blog/winnerbao/532634

相關推薦

[]檔案互斥

該文是2005年底在老東家開發監控程式時遇到的一個經典問題。回過頭看來,竟然有同學(或者老師)看了該文,並給出了一條非常給力的評價,深感榮幸。 返回頭看這篇文章,基本上給人一種凌亂的感覺,幸運的是沒有多少人看過。作為對自己的反省,將該文重新整理結構,梳理結果。原文將作為歷史文物保留。 問題提出:系統程序/

多個地方同時向一個檔案互斥問題解決方案

場景:多個地方同時向一個檔案讀寫據,如何保持操作互斥性,即一次只能一個操作(比如讀或寫)進行。 我們希望在一個執行緒在操作某個檔案的時候,其他執行緒不能對該檔案進行讀或寫操作,要怎麼才能實現呢?利用java提供的synchronized似乎無法完成,因為每個執行緒是在程

PGM格式影象檔案

        private int mWidth;         private int mLength;         private int mColor;

Java 之 檔案及效能比較總結

Java 之 檔案讀寫及效能比較總結 2014年05月12日 17:56:49 閱讀數:21765  幹Java這麼久,一直在做WEB相關的專案,一些基礎類差不多都已經忘記。經常想得撿起,但總是因為一些原因,不能如願。 其實不是沒有時間,只是有些時候疲於總結,今得空,下定決心

json.dump json.load與檔案操作

一.寫檔案 info={"name":"李小龍",'age':66,'love':"cat"} fp=open('testdict1.txt','w+',encoding='utf-8') fp.write(info) ls=list('1234567890') # print(ls) f

C檔案函式

fopen() 函式原型 函式原型:FILE * fopen(const char * path, const char * mode); FILE *fp ; fp = fopen("D:\\a.txt","r"); \\是一種轉義字元,他表示一個\,就像\n表示回車一樣,即

NOIP複賽複習(三)檔案與數論模板

檔案讀入讀出 假設題目名為“add”,那麼資料夾名為“add”,c++程式名為“add.cpp”,讀入檔名為“add.in”,輸出檔名為“add.out”。四個的拼寫均不可有誤,包括大小寫差異。千萬不要除錯後就忘記修改檔案讀入讀出了。  #include<cstdio&

C/C++檔案操作 —— windowsAPI

轉自:http://blog.sina.com.cn/s/blog_6e7fed390100z0j1.html 基於C的檔案操作 在ANSI C中,對檔案的操作分為兩種方式,即流式檔案操作和I/O檔案操作,下面就分別介紹之。 一、流式檔案操作 這種方式的檔案操作有一個重要的結構

Python基本語法之文字檔案

  檔案讀寫相關係統函式說明 系統函式 說明 input(tips); 提示使用者輸入資訊,例如 str = input("Please input your ip:") 將輸入的資訊賦值給變數

HDFS檔案操作 (通俗易懂)

首先來介紹兩個概念 ▪NameNode:領導級別。管 NameNode:領導級別。管理資料塊對映;處理客戶端的讀寫請求;配置副本策略;管理HDFS的名稱空間; DataNode:員工級別。負責儲存客戶端發來的資料塊block;執行資料塊的讀寫操作。 理資料 寫詳細步驟: 1、首先

python學習(四)檔案

三種模式介紹:#r只讀模式,預設的,未指定模式時為只讀 r 開啟檔案不存在的話,會報錯 ; r+ 讀寫模式 #寫模式 w 會將原來檔案中的內容清空 開啟檔案不存在的話,會新建一個檔案 w+ 寫讀模式,雖然能讀,但是因為把檔案內容清空了,讀到的就是空 #追加模式 a+ 追加讀模式

沉澱再出發:java的檔案

沉澱再出發:java的檔案讀寫 一、前言   對於java的檔案讀寫是我們必須使用的一項基本技能,因此瞭解其中的原理,位元組流和字元流的本質有著重要的意義。 二、java中的I/O操作  2.1、檔案讀寫的本質    概念框架: 1 方式

unity3d本地檔案

 今天要做一個移動平臺的版本控制,先做一個前期的工作,就是從伺服器端載入資源,然後讀取到本地,再從本地讀取資源。這裡就以pc平臺為例,移動平臺也是一樣,就是稍微做一點路徑上的修改, 下面是不同平臺路徑的預編譯:   view sou

React Native檔案操作

最近公司專案要求進行定時上傳位置資訊,及埋點,因為使用的是RN開發,一開始就是想到在Android和Ios原生裡進行操作。 在原生裡面實現了定時任務,Android裡面使用的是broadcastReceive + service + timer實現了。 現在需要生成一個日誌檔案,一開始想在原生裡面進

node——1-node 的初始化 及 檔案

node 初始化(helloworld) 新建 helloworld.js 檔案,內容如下: var foo = 'hello world!'; console.log(foo); // 在 node 中,採用 EcmaScript 進行編碼 // 沒有 BOM、DOM,和瀏覽

python檔案指南(二)

我們知道當檔案不存在的時候,open()方法的寫模式與追加模式都會新建檔案,但是對檔案進行判斷的場景還有很多,比如,在爬蟲下載圖片的時候,可能需要判斷檔案是否存在,以免重複下載;又比如,建立新檔案的時候,可能需要判斷檔案是否存在,存在就先做個備份......所以,學習判斷檔案是否存在,還是很有必要的

python檔案指南(一)

目錄   如何將列表資料寫入檔案? 如何從檔案中讀取內容? 多樣需求的讀寫任務 從with語句到上下文管理器 如何將列表資料寫入檔案? 首先,我們來看看下面這段程式碼,並思考:這段程式碼有沒有問題,如果有問題的話,要怎麼改? li = 

matlab 檔案、資料讀取

目錄   1-檔案開啟與關閉 2-使用函式讀取文字資料 3-讀取數值型文字資料 4-讀取含有分隔符的ASCII資料檔案 5-二進位制資料的讀寫 6-使用檔案I/O函式 7-MAT檔案 1-檔案開啟與關閉  fopen('filename

【iOS】第03講 檔案/NSArray/NSData/NSFileManager/NSFileHandle

一、沙盒    模擬器上的沙盒目錄路徑    ~/Library/Application Support/iPhone Simulator/6.0/Applications         &n

java檔案詳細介紹

主要針對java中檔案的概念以及一些用法 ·java中檔案讀寫操作基於流這個概念 流各種方法存在於java.io包中檔案是資料流中最常用的一.檔案的相關方法歸類:建立:File 物件名=new File("檔名");讀取:·File 物件名=new File("檔案路徑");  &nb