linux系統編程之文件與I/O(六):fcntl 函數與文件鎖

?

?

?分類:
linux系統編程(19)?

一、fcntl函數

功能:操縱文件描述符,改變已打開的文件的屬性

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

?

cmd的取值可以如下:

復制文件描述符
F_DUPFD (long)


設置/獲取文件描述符標志
F_GETFD (void)
F_SETFD (long)


設置/獲取文件狀態標志
F_GETFL (void)
F_SETFL (long)


獲取/設置文件鎖
F_GETLK
F_SETLK,F_SETLKW

?

其中復制文件描述符可參見《linux系統編程之文件與I/O(五):打開文件的內核結構file和重定向》,文件描述符的標志只有一個即FD_CLOEXEC,設置/獲取文件描述符標志看這里。下面先來看設置/獲取文件狀態標志。

F_SETFL:

On Linux ?this ?command?can change only the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK flags.

示例程序如下:

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
?
/*************************************************************************
????>?File?Name:?file_fcntl.c
????>?Author:?Simba
????>?Mail:?dameng34@163.com
????>?Created?Time:?Sat?23?Feb?2013?02:34:02?PM?CST
?************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

#define?ERR_EXIT(m)?\
????do?{?\
????????perror(m);?\
????????exit(EXIT_FAILURE);?\
????}?while(0)

void?set_flag(int,?int);
void?clr_flag(int,?int);

int?main(int?argc,?char?*argv[])
{
????char?buf[1024]?=?{0};
????int?ret;
????/*
????????int?flags;
????????flags?=?fcntl(0,?F_GETFL,?0);
????????if?(flags?==?-1)
????????????ERR_EXIT("fcntl?get?flag?error");
????????ret?=?fcntl(0,?SETFL,?flags?|?O_NONBLOCK);?//設置為非阻塞,但不更改其他狀態
????????if?(ret?==?-1)
????????????ERR_EXIT("fcntl?set?flag?error");
????*/
????set_flag(0,?O_NONBLOCK);
????ret?=?read(0,?buf,?1024);
????if?(ret?==?-1)
????????ERR_EXIT("read?error");

????printf("buf=%s\n",?buf);
????return?0;
}

void?set_flag(int?fd,?int?flags)
{
????int?val;
????val?=?fcntl(fd,?F_GETFL,?0);
????if?(val?==?-1)
????????ERR_EXIT("fcntl?get?flag?error");
????val?|=?flags;
????if?(fcntl(fd,?F_SETFL,?val)?<?0)
????????ERR_EXIT("fcntl?set?flag?error");
}

void?clr_flag(int?fd,?int?flags)
{
????int?val;
????val?=?fcntl(fd,?F_GETFL,?0);
????if?(val?==?-1)
????????ERR_EXIT("fcntl?get?flag?error");
????val?&=?~flags;
????if?(fcntl(fd,?F_SETFL,?val)?<?0)
????????ERR_EXIT("fcntl?set?flag?error");
}
測試輸出:

?

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_fcntl?
read error: Resource temporarily unavailable

因為將標準輸入的狀態更改為非阻塞,則read不會阻塞等待輸入而立即返回錯誤,errno將被置為EAGAIN,即可以重新嘗試。

?

二、文件鎖結構體

struct flock {
...
short l_type; ? ? ? /* Type of lock: F_RDLCK,
? ? ? ? F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; ? ? ? /* Starting offset for lock */
off_t l_len; ? ? ? ? /* Number of bytes to lock */
pid_t l_pid; ? ? ? ?/* PID of process blocking our lock
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(F_GETLK only) */
? ? ?...
};

文件鎖的類型只有兩種,一種是寫鎖也叫排他鎖,一種是讀鎖也就共享鎖,可以有多個進程各持有一個讀鎖,但只能有一個進程持有寫鎖,只有對文件有對應的讀寫權限才能施加對應的鎖類型。中間三個參數 l_whence, ?l_start, l_len 決定了被鎖定的文件范圍。當fcntl 函數的cmd為F_GETLK時,flock 結構體的 l_pid 參數會返回持有寫鎖的進程id。進程退出或者文件描述符被關閉時,會釋放所有的鎖。

?

示例程序如下:

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
?
/*************************************************************************
????>?File?Name:?file_flock.c
????>?Author:?Simba
????>?Mail:?dameng34@163.com
????>?Created?Time:?Sat?23?Feb?2013?02:34:02?PM?CST
?************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

#define?ERR_EXIT(m)?\
????do?{?\
????????perror(m);?\
????????exit(EXIT_FAILURE);?\
????}?while(0)


int?main(int?argc,?char?*argv[])
{
????int?fd;
????fd?=?open("test2.txt",?O_CREAT?|?O_RDWR?|?O_TRUNC,?0664);
????if?(fd?==?-1)
????????ERR_EXIT("open?error");
????/*?只有對文件有相應的讀寫權限才能施加對應的文件鎖?*/
????struct?flock?lock;
????memset(&lock,?0,?sizeof(lock));
????lock.l_type?=?F_WRLCK;?//?排他鎖,即不允許其他進程再對其加任何類型的鎖,但讀鎖(共享鎖)允許
????lock.l_whence?=?SEEK_SET;
????lock.l_start?=?0;?//從文件開頭開始鎖定
????lock.l_len?=?0;?//?文件全部內容鎖住

????if?(fcntl(fd,?F_SETLK,?&lock)?==?0)
????{
????????/*?若為F_SETLKW,這時如果鎖已經被其他進程占用,則此進程會阻塞直到其他進程釋放鎖*/
????????printf("lock?success\n");
????????printf("press?any?key?to?unlock\n");
????????getchar();
????????lock.l_type?=?F_UNLCK;
????????if?(fcntl(fd,?F_SETLK,?&lock)?==?0)
????????????printf("unlock?success\n");
????????else
????????????ERR_EXIT("unlock?fail");
????}
????else
????????ERR_EXIT("lock?fail");

????return?0;?//進程退出會對所有文件解鎖
}

?

測試如下:

我們先在一個 終端執行程序:

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_flock?
lock success
press any key to unlock

?

現在文件已經被鎖住了,而且沒有按下任何按鍵,所以卡在這里,也還沒解鎖,接著在另一個終端再次執行同個程序:

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_flock?
lock fail: Resource temporarily unavailable

會立即返回錯誤,因為我們希望施加的是排他鎖,而現在前面一個進程正在占用寫鎖還沒釋放,所以嘗試施加鎖失敗,而如果fcntl 函數的cmd 設置為 F_SETLKW,即帶w的版本,則此進程會一直阻塞直到前面一個進程釋放了鎖。

?

參考:《APUE》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/542572.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542572.shtml
英文地址,請注明出處:http://en.pswp.cn/news/542572.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 使用異常函數_您如何測試Python函數引發異常?

python 使用異常函數This article elaborates on how to implement a test case for a function that raises an exception. 本文詳細介紹了如何為引發異常的函數實現測試用例 。 Consider the following function: 考慮以下功能&#xff1a; import redef check_email_forma…

php 遠程圖片合拼,PHP實現將幾張照片拼接到一起的合成圖片功能【便于整體打印輸出】...

本文實例講述了PHP實現將幾張照片拼接到一起的合成圖片功能。共享給大家供大家參考&#xff0c;詳細如下&#xff1a;/*** 作品合成程序* 針對單面&#xff0c;封面不做特殊處理*/$src_path $argv[1]; // php該文件&#xff0c;第一個參數是文件夾名(作品集)&#xff0c;可相對…

bandizip最后一個無廣告版本_如果非要選擇一款壓縮軟件的話——Bandizip

全世界只有不到0.00~1 % 的人關注了我們得到你的關注是小幫的幸運壓縮解壓軟件是電腦一個必備軟甲&#xff0c;前面的文章介紹了一款開源小巧無廣告的壓縮解壓軟件windows工具軟件選擇之壓縮軟件——7-Zip&#xff0c;如果有人用不慣的話可以試試今天的這款。Bandizip 是一款來…

[MVC學習筆記]1.項目結構搭建及單個類在各個層次中的實現

新人剛開始學習ASP.NET MVC&#xff0c;若有不足之處希望能得到您的指點&#xff0c;不勝感激&#xff01; 先來一張項目的層級結構圖: Model&#xff1a;模型層&#xff0c;主要是各種類型、枚舉以及ORM框架&#xff0c;框架完成數據庫和實體類的映射。項目中選用了微軟的開源…

日期getUTCSeconds()方法以及JavaScript中的示例

JavaScript日期getUTCSeconds()方法 (JavaScript Date getUTCSeconds() method) getUTCSeconds() method is a Dates class method and it is used to get seconds from the current time according to the UTC (Universal time coordinated). getUTCSeconds()方法是Date的類方…

dedecms 在模板里引入php文件夾,dedecms如何添加并引入php文件

前言&#xff1a;有些時候我們需要創建一些單獨的PHP文件&#xff0c;但是隨便放入的PHP文件是不能夠編譯織夢 dedecms的標簽的&#xff0c;所以我們需要引入織夢標簽的編譯引擎方案。例如&#xff0c;我們在根目錄創建 example.php&#xff0c;代碼如下&#xff1a;<?php …

mybatisplus代碼生成器_想做時間管理大師?你可以試試Mybatis Plus代碼生成器

1. 前言對于寫Crud的老司機來說時間非常寶貴&#xff0c;一些樣板代碼寫不但費時費力&#xff0c;而且枯燥無味。經常有小伙伴問我&#xff0c;胖哥你怎么天天那么有時間去搞新東西&#xff0c;透露一下秘訣唄。好吧&#xff0c;今天就把Mybatis-plus的代碼生成器分享出來&…

安裝Oracle 11g RAC R2 之Linux DNS 配置

Oracle 11g RAC 集群中引入了SCAN(Single Client Access Name)的概念&#xff0c;也就是指集群的單客戶端訪問名稱。SCAN 這個特性為客戶端提供了單一的主機名&#xff0c;用于訪問集群中運行的 Oracle 數據庫。如果您在集群中添加或刪除節點&#xff0c;使用 SCAN 的客戶端無需…

c++ websocket客戶端_websocket使用

websocket使用一、介紹在項目開發過程中&#xff0c;很多時候&#xff0c;我們不可避免的需要實現的一個功能&#xff1a; 服務端實時發送信息給客戶端。比如實時公告、實時訂單通知、實時報警推送等等&#xff0c;登錄后的客戶端需要知道與它相關的實時信息&#xff0c;以便進…

漢子編碼比字母編碼長_字母/博客作者編碼問題(使用動態編程)

漢子編碼比字母編碼長Problem statement: 問題陳述&#xff1a; Shivang is a blog writer and he is working on two websites simultaneously. He has to write two types of blogs which are: Shivang是一位博客作家&#xff0c;他同時在兩個網站上工作。 他必須寫兩種類型…

php parent報錯,mac brew 安裝php擴展報錯:parent directory is world writable but not sticky

$ brew install php70-mcrypt報錯&#xff1a;Error: parent directory is world writable but not sticky搜索到github的答案https://github.com/Homebrew/legacy-homebrew/issues/40345原因&#xff1a;/tmp目錄權限不對$ ls -ld /private/tmp打印出來 /private/tmp 被標黃了…

在cordova中使用HTML5的多文件上傳

2019獨角獸企業重金招聘Python工程師標準>>> 我們先看看linkface給開放的接口&#xff1a; 字段類型必需描述api_idstring是API 賬戶api_secretstring是API 密鑰selfie_filefile見下方注釋需上傳的圖片文件 1&#xff0c;上傳本地圖片進行檢測時選取此參數selfie_ur…

python dataframe切片_python pandas dataframe 行列選擇,切片操作方法

SQL中的select是根據列的名稱來選取&#xff1b;Pandas則更為靈活&#xff0c;不但可根據列名稱選取&#xff0c;還可以根據列所在的position&#xff08;數字&#xff0c;在第幾行第幾列&#xff0c;注意pandas行列的position是從0開始&#xff09;選取。相關函數如下&#xf…

php根據設備判斷訪問,PHP判斷設備訪問來源

/*** 判斷用戶請求設備是否是移動設備* return bool*/function isMobile() {//如果有HTTP_X_WAP_PROFILE則一定是移動設備if (isset($_SERVER[HTTP_X_WAP_PROFILE])) {return true;}//如果via信息含有wap則一定是移動設備,部分服務商會屏蔽該信息if (isset($_SERVER[HTTP_VIA])…

機器學習 深度學習 ai_如何學習機器學習和人工智能?

機器學習 深度學習 aiSTRATEGY 戰略 Learn theory practical aspects. 學習理論和實踐方面的知識。 (At first get an overview of what you are going to learn). (首先獲得要學習的內容的概述)。 Gain a good hold/insight on each concept. 掌握/理解每個概念。 If you …

linux常用命令和配置

2019獨角獸企業重金招聘Python工程師標準>>> 啟動php&#xff1a; /etc/init.d/php-fpm restart 查看PHP運行目錄&#xff1a; which php /usr/bin/php 查看php-fpm進程數&#xff1a; ps aux | grep -c php-fpm 查看運行內存 /usr/bin/php -i|grep mem iptables如…

centos7時間同步_centos 8.x系統配置chrony時間同步服務

centos 8.x系統配置chrony時間同步服務CentOS 7.x默認使用的時間同步服務為ntp服務&#xff0c;但是CentOS 8開始在官方的倉庫中移除了ntp軟件&#xff0c;換成默認的chrony進行時間同步的服務&#xff0c;chrony既可以作為客戶端向其他時間服務器發送時間同步請求&#xff0c;…

php可以用scanf,C/C++中 使用scanf和printf如何讀入輸出double型數據。

黃舟2017-04-17 13:47:232樓注意scanf函數和printf函數是不同尋常的函數&#xff0c;因為它們都沒有將函數的參數限制為固定數量。scanf函數和printf函數又可變長度的參數列表。當調用帶可變長度參數列表的函數時&#xff0c;編譯器會安排float參數自動轉換成為double類型&…

ICWAI和ICWA的完整形式是什么?

ICWAI / ICWA&#xff1a;印度成本與工程會計師協會/印度兒童福利法 (ICWAI / ICWA: Institute of Cost and Works Accountants of India / Indian Child Welfare Act) 1)ICWAI&#xff1a;印度成本與工程會計師協會 (1) ICWAI: Institute of Cost and Works Accountants of In…

深入研究java.lang.Runtime類【轉】

轉自&#xff1a;http://blog.csdn.net/lastsweetop/article/details/3961911 目錄(?)[-] javalang 類 RuntimegetRuntimeexitaddShutdownHookremoveShutdownHookhaltrunFinalizersOnExitexecexecexecexecexecexecavailableProcessorsfreeMemorytotalMemorymaxMemorygcrunFina…