Linux程序同步之記錄鎖

2021-07-25 10:02:56 字數 3980 閱讀 9429

記錄鎖相當於執行緒同步中讀寫鎖的一種擴充套件型別,可以用來對有親緣或無親緣關係的程序進行檔案讀與寫的同步

,通過fcntl

函式來執行上鎖操作。儘管讀寫鎖也可以通過在共享記憶體區來進行程序的同步,但是

fcntl

記錄上鎖往往更容易使用,且效率更高。

記錄鎖的功能:當乙個程序正在讀或修改檔案的某個部分是,它可以阻止其他程序修改同一檔案區。

對於這個功能闡述我認為有三點要解釋的:

記錄鎖函式介面

記錄上鎖的posix

介面函式

fcntl

如下:

/* do the file control operation described by cmd on fd.

the remaining arguments are interpreted depending on cmd. */

int fcntl (int __fd, int __cmd, ...);

//根據cmd的不同有以下三種型別的呼叫

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

int fcntl(int fd, int cmd, struct flock *lock);

由函式名稱可知fcntl

的功能是對檔案的控制操作,根據傳入不同的操作型別命令

cmd,

fcntl

會執行不同的操作,

fcnt

根據cmd

不同,接收可變的引數。具體有以下五種型別的操作:

/*

cmd = f_dupfd,複製乙個檔案描述符;

*/int fcntl(int fd, int cmd);

/*cmd = f_getfd,獲得檔案描述符標誌;

cmd = f_setfd,設定檔案描述符標誌;arg = 描述符標誌的值,目前只定義了乙個標誌: fd_cloexec

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

*//*

cmd = f_getfl,獲得檔案狀態標誌;

cmd = f_setfl,設定檔案狀態標誌;arg = 狀態標誌的值

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

*//*

cmd = f_getown,獲得當前接收sigio和sigurg訊號的程序id或程序組id

cmd = f_setown,設定接收sigio和sigurg訊號的程序id或程序組id;arg = 程序id或程序組id

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

*//*

return value:

對於成功的呼叫,根據操作型別cmd不同,有以下幾種情況:

f_dupfd 返回新的檔案描述符

f_getfd 返回檔案描述符標誌

f_getfl 返回檔案狀態標誌

f_getown 程序id或程序組id

all other commands 返回0

呼叫失敗, 返回-1,並設定errno。

*/

上面四個功能都是fcntl

提供的很常用的操作,關於記錄鎖的功能就是

fcntl

提供的第五個功能,具體使用如下:

int fcntl(int fd, int cmd, struct flock *lock);

/*cmd = f_getlk,測試能否建立一把鎖

cmd = f_setlk,設定鎖

cmd = f_setlkw, 阻塞設定一把鎖

*///posix只定義fock結構中必須有以下的資料成員,具體實現可以增加

struct flock ;

//return value: 前面已經說明;

l f_setlk:獲取(l_type

為f_rdlck

或f_wrlck

)或釋放由

lock

指向flock

結構所描述的鎖,如果無法獲取鎖時,該函式會立即返回乙個

eaccess

或eagain

錯誤,而不會阻塞。

l f_setlkw:f_setlkw和

f_setlk

的區別是,無法設定鎖的時候,呼叫執行緒會阻塞到該鎖能夠授權位置。

l f_getlk:if_getlk主要用來檢測是否有某個已存在鎖會妨礙將新鎖授予呼叫程序,如果沒有這樣的鎖,

lock

所指向的

flock

結構的l_type

成員就會被置成

f_unlck

,否則已存在的鎖的資訊將會寫入

lock

所指向的

flock

結構中

這裡需要注意的是,用f_getlk

測試能否建立一把鎖,然後接著用

f_setlk

或f_setlkw

企圖建立一把鎖,由於這兩者不是乙個原子操作,所以不能保證兩次

fcntl

之間不會有另外乙個程序插入並建立一把相關的鎖,從而使一開始的測試情況無效。所以一般不希望上鎖時阻塞,會直接通過呼叫

f_setlk

,並對返回結果進行測試,以判斷是否成功建立所要求的鎖。

記錄鎖規則說明

前面我們說了記錄鎖相當於讀寫鎖的一種擴充套件型別,記錄鎖和讀寫鎖一樣也有兩種鎖:共享讀鎖(f_rdlck

)和獨佔寫鎖(

f_wrlck

)。在使用規則上和讀寫鎖也基本一樣:

如下表所示:

需要說明的是:上面所闡述的規則只適用於不同程序提出的鎖請求,並不適用於單個程序提出的多個鎖請求。即如果乙個程序對乙個檔案區間已經有了一把鎖,後來該程序又試圖在同一檔案區間再加一把鎖,那麼新鎖將會覆蓋老鎖。

下面進行測試;第乙個程式是在同一程序中測試能否在加寫鎖後,繼續加讀寫鎖。第二個程式是在在父程序中加寫鎖後,然後再子程序中測試能否繼續加讀寫鎖。

//呼叫的函式,在文章末尾貼出

int main()

int readw_lock(int fd)

struct flock lock;

lock_init(&lock, f_rdlck, seek_set, 0, 0);

if (fcntl(fd, f_setlkw, &lock) != 0)

return 0;

}int writew_lock(int fd)

struct flock lock;

lock_init(&lock, f_wrlck, seek_set, 0, 0);

if (fcntl(fd, f_setlkw, &lock) != 0)

return 0;

}int unlock(int fd)

struct flock lock;

lock_init(&lock, f_unlck, seek_set, 0, 0);

if (fcntl(fd, f_setlkw, &lock) != 0)

return 0;

}pid_t lock_test(int fd, short type, short whence, off_t start, off_t len)

if(lock.l_type == f_unlck)

return 0;

return lock.l_pid;

}

本文**:

程序(同步)鎖

很多時候,我們需要在多個程序中同時寫乙個檔案,如果不加鎖機制,就會導致寫檔案錯亂 這個時候,我們可以使用multiprocessing.lock 我一開始是這樣使用的 from multiprocessing import process,lock 鎖要從從multiprocessing匯入 def...

python程序同步鎖

同步鎖 通常被用來實現共享資源的同步訪問,為每乙個共享資源建立乙個lock物件當你需要訪問該資源時,呼叫qcuqire方法來獲取鎖物件 如果其他執行緒已經獲得該鎖,則當前執行緒需等待期被釋放 待資源訪問完後,在呼叫release方法釋放鎖 死鎖 指倆個或倆個以上的程序或執行緒在執行過程中,因爭奪資源...

Linux下的程序同步機制 記錄鎖

當可能出現幾個程序爭用 讀 寫 同乙個critical section的時候,加鎖是常用的做法。linux加鎖的方法,除了經典的ipc semophore 之外,記錄鎖 record locking 提供了更簡單的方法。其實記錄鎖的名字叫檔案鎖會比較貼切一點,因為其加鎖和解鎖都是通過對檔案的操作完成...