日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux系统编程之文件与I/O(六):fcntl 函数与文件锁

發布時間:2025/3/8 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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》

總結

以上是生活随笔為你收集整理的linux系统编程之文件与I/O(六):fcntl 函数与文件锁的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。