首頁  >  文章  >  系統教程  >  Linux 系統程式設計的技巧:使用 fcntl() 實作讀寫鎖

Linux 系統程式設計的技巧:使用 fcntl() 實作讀寫鎖

WBOY
WBOY轉載
2024-02-13 16:03:24871瀏覽

讀寫鎖是一種常用的同步機制,它可以讓多個行程或執行緒對同一個資源進行並發的讀取操作,或是互斥的寫入操作,從而提高系統的效率和安全性。在 Linux 系統程式設計中,有多種方法可以實作讀寫鎖,例如使用 pthread 函式庫、使用檔案鎖等。本文將為你介紹一種使用 fcntl() 系統呼叫實作讀寫鎖的方法,以及它的原理、用法和優缺點,讓你在 Linux 系統程式設計中更好地使用和理解這個技巧。

Linux 系统编程的一种技巧:使用 fcntl() 实现读写锁

#在多進程對同一個檔案進行讀寫存取時,為了確保資料的完整性,有事需要對檔案進行鎖定。可以透過fcntl()函數對檔案進行鎖定和解鎖。

\1. fcntl

1.1.功能描述:根據文件描述詞來操作文件的特性。

1.2.用法:

int fcntl(int fd, int cmd);

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

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

fd:檔案描述詞。

cmd:操作指令。

arg:供指令使用的參數,是否需要arg參數跟cmd指令有關。

lock:鎖定資訊。

2.讀寫鎖定實例

新建兩個文件,原始碼如下2.1、2.2所示。

2.1.為檔案加讀鎖定

#include 

\#include 

\#include 

\#include 

\#include 

int main(int argc, const char * argv [ ])

{

int fd = open("test.c", O_RDONLY);

if (fd == -1)

{

perror("open failed:");

return -1;

}

struct stat sta;

fstat(fd,&sta);

struct flock lock;  

lock.l_len = sta.st_size;

lock.l_pid = getpid();

lock.l_start = 0;

lock.l_type = F_RDLCK;

lock.l_whence = SEEK_SET;

printf("进程pid: %d\n",lock.l_pid);

if(fcntl(fd,F_SETLK,&lock) == -1)

{

perror("fcntl fail ");

return -1;

}

else

{

printf("add read lock success!\n");

}

sleep(10);

close(fd);

return 0;

}

2.2.给文件加写锁

\#include 

\#include 

\#include 

\#include 

\#include 

int main(int argc, const char * argv [ ])

{

int fd = open("test.c", O_WRONLY);

if (fd == -1)

{

perror("open failed:");

return -1;

}

struct stat sta;

fstat(fd,&sta);

struct flock lock;  

lock.l_len = sta.st_size;

lock.l_pid = getpid();

lock.l_start = 0;

lock.l_type = F_WRLCK;

lock.l_whence = SEEK_SET;

printf("进程pid: %d\n",lock.l_pid);

while(fcntl(fd,F_SETLK,&lock) == -1 )

{

perror("fcntl:");

sleep(1);

struct flock lock_1;

lock_1 = lock;

lock_1.l_type = F_WRLCK;  //

fcntl(fd,F_GETLK,&lock_1);//获取文件锁状态,及加锁(lock_1.l_type)能否成功

switch(lock_1.l_type)

{

case F_RDLCK:

printf("检测到读锁 pid = %d \n",lock_1.l_pid);

break;

case F_WRLCK:

printf("检测到写锁 pid = %d \n",lock_1.l_pid);

break;

case F_UNLCK:

printf("检测到已解锁.pid = %d \n",lock_1.l_pid);

}

}

printf("写锁设置成功\n");

getchar();

close(fd);

return 0;

}


/*

注意:

1、fcntl(fd,F_GETLK,&lock_1)中的lock_1必須初始化,且lock_1.l_type必須設定為對應的鎖,才能確定能否加鎖成功,及不成功的原因。

2、GETLK時,fcntl先偵測有沒有能阻止本次加鎖的鎖,如果有,則覆寫flock結構體(lock_1)的資訊。如果沒有,則置lock_1.l_type 的類型為F_UNLCK。

*/

對於寫鎖(F_WRLCK 獨佔鎖),只有一個程序可以在檔案的任一特定區域上享有獨佔鎖。

對於讀鎖(F_RDLCK 共用鎖定),許多不同的程序可以同時擁有檔案上同一區域上的共用鎖定。為了擁有共享鎖,文件必須以讀取或讀取/寫入的方式開啟。只要任一進程擁有共享鎖,那麼其他進程就無法再獲得獨佔鎖。

分別編譯執行:

3.先執行讀鎖,再執行寫入鎖定。結果如下:

#
liu@ubuntu:~/learn/lrn_linux$ ./readlock.out 

进程pid: 16458

add read lock success!

liu@ubuntu:~/learn/lrn_linux$ ./writelock.out 

进程pid: 16459

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到读锁 pid = 16458 

fcntl:: Resource temporarily unavailable

检测到已解锁.pid = 16459 

寫入鎖定設定成功

可以看出,當檔案被讀鎖定佔用時,無法新增寫入鎖定(獨佔鎖定)

4.先運行寫鎖,再運行讀鎖的話,結果如下:

liu@ubuntu:~/learn/lrn_linux$ ./writelock.out 

進程pid: 16349

寫入鎖定設定成功

liu@ubuntu:~/learn/lrn_linux$ ./readlock.out 

進程pid: 16350

fcntl fail : Resource temporarily unavailable

所以,加鎖是成功的。

透過本文,你應該對 Linux 系統程式設計中使用 fcntl() 實作讀寫鎖的方法有了一個基本的了解,知道了它的原理、用法和優缺點。你也應該明白了使用 fcntl() 實作讀寫鎖的目的和影響,以及如何在 Linux 系統程式設計中正確地使用和配置 fcntl()。我們建議你在需要實現讀寫鎖的場景中,使用 fcntl() 來實現你的目標。同時,我們也提醒你在使用 fcntl() 時要注意一些潛在的問題和挑戰,如相容性、可移植性、效能等。希望這篇文章能幫助你更好地使用 Linux 系統編程,讓你在 Linux 下掌握 fcntl() 的技巧和優勢。

以上是Linux 系統程式設計的技巧:使用 fcntl() 實作讀寫鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除