目錄
linux中fcntl()、lockf、flock的区别
1.flock
2.lockf与fcntl
3.两种锁的关系
首頁 php教程 php手册 linux中fcntl()、lockf、flock的区别

linux中fcntl()、lockf、flock的区别

Jun 13, 2016 am 08:43 AM
android

linux中fcntl()、lockf、flock的区别

fcntl()、lockf、flock的区别
——lvyilong316

这三个函数的作用都是给文件加锁,那它们有什么区别呢?首先flock和fcntl是系统调用,而lockf是库函数。lockf实际上是fcntl的封装,所以lockf和fcntl的底层实现是一样的,对文件加锁的效果也是一样的。后面分析不同点时大多数情况是将fcntl和lockf放在一起的。下面首先看每个函数的使用,从使用的方式和效果来看各个函数的区别。

1.flock

l函数原型

#include

intflock(intfd,intoperation);//Applyorremoveanadvisorylockontheopenfilespecifiedbyfd,只是建议性锁

其中fd是系统调用open返回的文件描述符,operation的选项有:

LOCK_SH:共享锁

LOCK_EX:排他锁或者独占锁

LOCK_UN:解锁。

LOCK_NB:非阻塞(与以上三种操作一起使用)

关于flock函数,首先要知道flock函数只能对整个文件上锁,而不能对文件的某一部分上锁,这是于fcntl/lockf的第一个重要区别,后者可以对文件的某个区域上锁。其次,flock只能产生劝告性锁。我们知道,linux存在强制锁(mandatorylock)和劝告锁(advisorylock)。所谓强制锁,比较好理解,就是你家大门上的那把锁,最要命的是只有一把钥匙,只有一个进程可以操作。所谓劝告锁,本质是一种协议,你访问文件前,先检查锁,这时候锁才其作用,如果你不那么kind,不管三七二十一,就要读写,那么劝告锁没有任何的作用。而遵守协议,读写前先检查锁的那些进程,叫做合作进程。再次,flock和fcntl/lockf的区别主要在fork和dup。

(1)flock创建的锁是和文件打开表项(structfile)相关联的,而不是fd。这就意味着复制文件fd(通过fork或者dup)后,那么通过这两个fd都可以操作这把锁(例如通过一个fd加锁,通过另一个fd可以释放锁),也就是说子进程继承父进程的锁。但是上锁过程中关闭其中一个fd,锁并不会释放(因为file结构并没有释放),只有关闭所有复制出的fd,锁才会释放。测试程序入程序一。

l程序一


<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>#include <stdio.h><br /></li><li>#include <unistd.h><br /></li><li>#include <stdlib.h><br /></li><li>#include <sys/file.h><br /></li><li>int main (int argc, char ** argv)<br /></li><li>{<br /></li><li>int ret;<br /></li><li>int fd1 = open("./tmp.txt",O_RDWR);<br /></li><li>int fd2 = dup(fd1);<br /></li><li>printf("fd1: %d, fd2: %d\n", fd1, fd2);<br /></li><li>ret = flock(fd1,LOCK_EX);<br /></li><li>printf("get lock1, ret: %d\n", ret);<br /></li><li>ret = flock(fd2,LOCK_EX);<br /></li><li>printf("get lock2, ret: %d\n", ret);<br /></li><li>return 0;<br /></li><li>}</li></ol>
登入後複製

运行结果如图,对fd1上锁,并不影响程序通过fd2上锁。对于父子进程,参考程序二。

l程序二

<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>#include <stdio.h><br /></li><li>#include <unistd.h><br /></li><li>#include <stdlib.h><br /></li><li>#include <sys/file.h><br /></li><li>int main (int argc, char ** argv)<br /></li><li>{<br /></li><li>int ret;<br /></li><li>int pid;<br /></li><li>int fd = open("./tmp.txt",O_RDWR);<br /></li><li>if ((pid = fork()) == 0){<br /></li><li>ret = flock(fd,LOCK_EX);<br /></li><li>printf("chile get lock, fd: %d, ret: %d\n",fd, ret);<br /></li><li>sleep(10);<br /></li><li>printf("chile exit\n");<br /></li><li>exit(0);<br /></li><li>}<br /></li><li>ret = flock(fd,LOCK_EX);<br /></li><li>printf("parent get lock, fd: %d, ret: %d\n", fd, ret);<br /></li><li>printf("parent exit\n");<br /></li><li>return 0;<br /></li><li>}</li></ol>
登入後複製

运行结果如图,子进程持有锁,并不影响父进程通过相同的fd获取锁,反之亦然。

(2)使用open两次打开同一个文件,得到的两个fd是独立的(因为底层对应两个file对象),通过其中一个加锁,通过另一个无法解锁,并且在前一个解锁前也无法上锁。测试程序如程序三:

l程序三

<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li style="text-align:left;">#include <stdio.h><br /></li><li style="text-align:left;">#include <unistd.h><br /></li><li style="text-align:left;">#include <stdlib.h><br /></li><li style="text-align:left;">#include <sys/file.h><br /></li><li style="text-align:left;">int main (int argc, char ** argv)<br /></li><li style="text-align:left;">{<br /></li><li style="text-align:left;">int ret;<br /></li><li style="text-align:left;">int fd1 = open("./tmp.txt",O_RDWR);<br /></li><li style="text-align:left;">int fd2 = open("./tmp.txt",O_RDWR);<br /></li><li style="text-align:left;">printf("fd1: %d, fd2: %d\n", fd1, fd2);<br /></li><li style="text-align:left;">ret = flock(fd1,LOCK_EX);<br /></li><li style="text-align:left;">printf("get lock1, ret: %d\n", ret);<br /></li><li style="text-align:left;">ret = flock(fd2,LOCK_EX);<br /></li><li style="text-align:left;">printf("get lock2, ret: %d\n", ret);<br /></li><li style="text-align:left;">return 0;<br /></li><li style="text-align:left;">}</li></ol>
登入後複製

结果如图,通过fd1获取锁后,无法再通过fd2获取锁。

(3)使用exec后,文件锁的状态不变。

(4)flock不能再NFS文件系统上使用,如果要在NFS使用文件锁,请使用fcntl。

(5)flock锁可递归,即通过dup或者或者fork产生的两个fd,都可以加锁而不会产生死锁。

2.lockf与fcntl

l函数原型

#include

intlockf(intfd,intcmd,off_tlen);

fd为通过open返回的打开文件描述符。

cmd的取值为:

F_LOCK:给文件互斥加锁,若文件以被加锁,则会一直阻塞到锁被释放。

F_TLOCK:同F_LOCK,但若文件已被加锁,不会阻塞,而回返回错误。

F_ULOCK:解锁。

F_TEST:测试文件是否被上锁,若文件没被上锁则返回0,否则返回-1。

len:为从文件当前位置的起始要锁住的长度。

通过函数参数的功能,可以看出lockf只支持排他锁,不支持共享锁。

#include

#include

intfcntl(intfd,intcmd,.../*arg*/);

structflock{

...

shortl_type;/*Typeoflock:F_RDLCK,F_WRLCK,F_UNLCK*/

shortl_whence;/*Howtointerpretl_start:SEEK_SET,SEEK_CUR,SEEK_END*/

off_tl_start;/*Startingoffsetforlock*/

off_tl_len;/*Numberofbytestolock*/

pid_tl_pid;/*PIDofprocessblockingourlock(F_GETLKonly)*/

...

};

文件记录加锁相关的cmd分三种:

F_SETLK:申请锁(读锁F_RDLCK,写锁F_WRLCK)或者释放所(F_UNLCK),但是如果kernel无法将锁授予本进程(被其他进程抢了先,占了锁),不傻等,返回error。

F_SETLKW:和F_SETLK几乎一样,唯一的区别,这厮是个死心眼的主儿,申请不到,就傻等。

F_GETLK:这个接口是获取锁的相关信息:这个接口会修改我们传入的structflock。

通过函数参数功能可以看出fcntl是功能最强大的,它既支持共享锁又支持排他锁,即可以锁住整个文件,又能只锁文件的某一部分。

下面看fcntl/lockf的特性:

(1)上锁可递归,如果一个进程对一个文件区间已经有一把锁,后来进程又企图在同一区间再加一把锁,则新锁将替换老锁。

(2)加读锁(共享锁)文件必须是读打开的,加写锁(排他锁)文件必须是写打开。

(3)进程不能使用F_GETLK命令来测试它自己是否再文件的某一部分持有一把锁。F_GETLK命令定义说明,返回信息指示是否现存的锁阻止调用进程设置它自己的锁。因为,F_SETLK和F_SETLKW命令总是替换进程的现有锁,所以调用进程绝不会阻塞再自己持有的锁上,于是F_GETLK命令绝不会报告调用进程自己持有的锁。

(4)进程终止时,他所建立的所有文件锁都会被释放,队医flock也是一样的。

(5)任何时候关闭一个描述符时,则该进程通过这一描述符可以引用的文件上的任何一把锁都被释放(这些锁都是该进程设置的),这一点与flock不同。如:

fd1=open(pathname,…);

lockf(fd1,F_LOCK,0);

fd2=dup(fd1);

close(fd2);

则在close(fd2)后,再fd1上设置的锁会被释放,如果将dup换为open,以打开另一描述符上的同一文件,则效果也一样。

fd1=open(pathname,…);

lockf(fd1,F_LOCK,0);

fd2=open(pathname,…);

close(fd2);

(6)由fork产生的子进程不继承父进程所设置的锁,这点与flock也不同。

(7)在执行exec后,新程序可以继承原程序的锁,这点和flock是相同的。(如果对fd设置了close-on-exec,则exec前会关闭fd,相应文件的锁也会被释放)。

(8)支持强制性锁:对一个特定文件打开其设置组ID位(S_ISGID),并关闭其组执行位(S_IXGRP),则对该文件开启了强制性锁机制。再Linux中如果要使用强制性锁,则要在文件系统mount时,使用_omand打开该机制。

3.两种锁的关系

那么flock和lockf/fcntl所上的锁有什么关系呢?答案时互不影响。测试程序如下:

<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>#include <unistd.h><br /></li><li>#include <stdio.h><br /></li><li>#include <stdlib.h><br /></li><li>#include <sys/file.h><br /></li><li>int main(int argc, char **argv)<br /></li><li>{<br /></li><li>int fd, ret;<br /></li><li>int pid;<br /></li><li>fd = open("./tmp.txt", O_RDWR);<br /></li><li>ret = flock(fd, LOCK_EX);<br /></li><li>printf("flock return ret : %d\n", ret);<br /></li><li>ret = lockf(fd, F_LOCK, 0);<br /></li><li>printf("lockf return ret: %d\n", ret);<br /></li><li>sleep(100);<br /></li><li>return 0;<br /></li><li>}</li></ol>
登入後複製

测试结果如下:

$./a.out

flockreturnret:0

lockfreturnret:0

可见flock的加锁,并不影响lockf的加锁。两外我们可以通过/proc/locks查看进程获取锁的状态。

$psaux|grepa.out|grep-vgrep

123751188490.00.011904440pts/5S+01:090:00./a.out

$sudocat/proc/locks|grep18849

1:POSIXADVISORYWRITE1884908:02:8526740EOF

2:FLOCKADVISORYWRITE1884908:02:8526740EOF

我们可以看到/proc/locks下面有锁的信息:我现在分别叙述下含义:

1)POSIXFLOCK这个比较明确,就是哪个类型的锁。flock系统调用产生的是FLOCK,fcntl调用F_SETLK,F_SETLKW或者lockf产生的是POSIX类型,有次可见两种调用产生的锁的类型是不同的;

2)ADVISORY表明是劝告锁;

3)WRITE顾名思义,是写锁,还有读锁;

4)18849是持有锁的进程ID。当然对于flock这种类型的锁,会出现进程已经退出的状况。

5)08:02:852674表示的对应磁盘文件的所在设备的主设备好,次设备号,还有文件对应的inodenumber。

6)0表示的是所的其实位置

7)EOF表示的是结束位置。这两个字段对fcntl类型比较有用,对flock来是总是0和EOF。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
新報告對傳聞中的三星 Galaxy S25、Galaxy S25 Plus 和 Galaxy S25 Ultra 相機升級進行了嚴厲的評估 新報告對傳聞中的三星 Galaxy S25、Galaxy S25 Plus 和 Galaxy S25 Ultra 相機升級進行了嚴厲的評估 Sep 12, 2024 pm 12:23 PM

最近幾天,Ice Universe 不斷披露有關 Galaxy S25 Ultra 的詳細信息,人們普遍認為這款手機將是三星的下一款旗艦智慧型手機。除此之外,洩密者聲稱三星只計劃升級一台相機

三星 Galaxy S25 Ultra 洩漏了第一張渲染圖,傳聞中的設計變化被曝光 三星 Galaxy S25 Ultra 洩漏了第一張渲染圖,傳聞中的設計變化被曝光 Sep 11, 2024 am 06:37 AM

OnLeaks 現在與 Android Headlines 合作,首次展示了 Galaxy S25 Ultra,幾天前,他試圖從他的 X(以前的 Twitter)粉絲那裡籌集到 4,000 美元以上的資金,但失敗了。對於上下文,嵌入在 h 下面的渲染圖像

IFA 2024 | TCL 的 NXTPAPER 14 在性能上無法與 Galaxy Tab S10 Ultra 相媲美,但在尺寸上幾乎可以與之媲美 IFA 2024 | TCL 的 NXTPAPER 14 在性能上無法與 Galaxy Tab S10 Ultra 相媲美,但在尺寸上幾乎可以與之媲美 Sep 07, 2024 am 06:35 AM

除了發布兩款新智慧型手機外,TCL 還發布了一款名為 NXTPAPER 14 的新 Android 平板電腦,其大螢幕尺寸是其賣點之一。 NXTPAPER 14 採用 TCL 標誌性品牌霧面液晶面板 3.0 版本

Vivo Y300 Pro 在 7.69 毫米纖薄機身中配備 6,500 mAh 電池 Vivo Y300 Pro 在 7.69 毫米纖薄機身中配備 6,500 mAh 電池 Sep 07, 2024 am 06:39 AM

Vivo Y300 Pro剛剛全面亮相,它是最薄的中階Android手機之一,配備大電池。準確來說,這款智慧型手機厚度僅為 7.69 毫米,但配備 6,500 mAh 電池。這與最近推出的容量相同

三星 Galaxy S24 FE 預計將以低於預期的價格推出,有四種顏色和兩種記憶體選項 三星 Galaxy S24 FE 預計將以低於預期的價格推出,有四種顏色和兩種記憶體選項 Sep 12, 2024 pm 09:21 PM

三星尚未就何時更新其 Fan Edition (FE) 智慧型手機系列提供任何提示。目前來看,Galaxy S23 FE 仍然是該公司的最新版本,於 2023 年 10 月年初推出。

新報告對傳聞中的三星 Galaxy S25、Galaxy S25 Plus 和 Galaxy S25 Ultra 相機升級進行了嚴厲的評估 新報告對傳聞中的三星 Galaxy S25、Galaxy S25 Plus 和 Galaxy S25 Ultra 相機升級進行了嚴厲的評估 Sep 12, 2024 pm 12:22 PM

最近幾天,Ice Universe 不斷披露有關 Galaxy S25 Ultra 的詳細信息,人們普遍認為這款手機將是三星的下一款旗艦智慧型手機。除此之外,洩密者聲稱三星只計劃升級一台相機

小米紅米 Note 14 Pro Plus 上市,成為首款配備 Light Hunter 800 相機的高通 Snapdragon 7s Gen 3 智慧型手機 小米紅米 Note 14 Pro Plus 上市,成為首款配備 Light Hunter 800 相機的高通 Snapdragon 7s Gen 3 智慧型手機 Sep 27, 2024 am 06:23 AM

Redmi Note 14 Pro Plus 現已正式成為去年 Redmi Note 13 Pro Plus 的直接後繼產品(亞馬遜售價 375 美元)。正如預期的那樣,Redmi Note 14 Pro Plus與Redmi Note 14和Redmi Note 14 Pro一起成為Redmi Note 14系列的主角。李

摩托羅拉 Razr 50s 在早期洩漏中顯示自己可能是新的預算可折疊手機 摩托羅拉 Razr 50s 在早期洩漏中顯示自己可能是新的預算可折疊手機 Sep 07, 2024 am 09:35 AM

摩托羅拉今年發布了無數設備,儘管其中只有兩款是可折疊的。就上下文而言,雖然世界上大多數地區都收到了 Razr 50 和 Razr 50 Ultra,但摩托羅拉在北美提供了 Razr 2024 和 Razr 2

See all articles