? ? ?在多進(jìn)程對(duì)同一個(gè)文件進(jìn)行讀寫訪問時(shí),為了保證數(shù)據(jù)的完整性,有事需要對(duì)文件進(jìn)行鎖定。可以通過fcntl()函數(shù)對(duì)文件進(jìn)行鎖定和解鎖。
1. fcntl
1.1.功能描述:根據(jù)文件描述詞來操作文件的特性。
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:供命令使用的參數(shù),是否需要arg參數(shù)跟cmd命令有關(guān)。?
lock:鎖信息。
2.讀寫鎖實(shí)例
新建兩個(gè)文件,源碼如下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("進(jìn)程pid: %d ",lock.l_pid);
if(fcntl(fd,F_SETLK,&lock) == -1)
{
perror("fcntl fail ");
return -1;
}
else
{
printf("add read lock success! ");
}
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("進(jìn)程pid: %d ",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);//獲取文件鎖狀態(tài),及加鎖(lock_1.l_type)能否成功
switch(lock_1.l_type)
{
case F_RDLCK:
printf("檢測(cè)到讀鎖 pid = %d ",lock_1.l_pid);
break;
case F_WRLCK:
printf("檢測(cè)到寫鎖 pid = %d ",lock_1.l_pid);
break;
case F_UNLCK:
printf("檢測(cè)到已解鎖.pid = %d ",lock_1.l_pid);
}
}
printf("寫鎖設(shè)置成功 ");
getchar();
close(fd);
return 0;
}
/*
注意:
1、fcntl(fd,F_GETLK,&lock_1)中的lock_1必須進(jìn)行初始化,并且lock_1.l_type必須設(shè)置為相應(yīng)的鎖,才能確定能否加鎖成功,及不成功的原因。
2、GETLK時(shí),fcntl先檢測(cè)有沒有能阻止本次加鎖的鎖,如果有,則覆蓋flock結(jié)構(gòu)體(lock_1)的信息。如果沒有,則置lock_1.l_type 的類型為F_UNLCK。
*/
對(duì)于寫鎖(F_WRLCK 獨(dú)占鎖),只有一個(gè)進(jìn)程可以在文件的任一特定區(qū)域上享有獨(dú)占鎖。
對(duì)于讀鎖(F_RDLCK 共享鎖),許多不同的進(jìn)程可以同時(shí)擁有文件上同一區(qū)域上的共享鎖。為了擁有共享鎖,文件必須以讀或者讀/寫的方式打開。只要任一進(jìn)程擁有共享鎖,那么其他進(jìn)程就無法再獲得獨(dú)占鎖。
分別編譯執(zhí)行:
3.先執(zhí)行讀鎖,再執(zhí)行寫鎖。結(jié)果如下:
liu@ubuntu:~/learn/lrn_linux$ ./readlock.out?
進(jìn)程pid: 16458
add read lock success!
liu@ubuntu:~/learn/lrn_linux$ ./writelock.out?
進(jìn)程pid: 16459
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到讀鎖 pid = 16458?
fcntl:: Resource temporarily unavailable
檢測(cè)到已解鎖.pid = 16459?
寫鎖設(shè)置成功
可以看出,當(dāng)文件被讀鎖占用時(shí),無法添加寫鎖(獨(dú)占鎖)
4.先運(yùn)行寫鎖,再運(yùn)行讀鎖的話,結(jié)果如下:
liu@ubuntu:~/learn/lrn_linux$ ./writelock.out?
進(jìn)程pid: 16349
寫鎖設(shè)置成功
liu@ubuntu:~/learn/lrn_linux$ ./readlock.out?
進(jìn)程pid: 16350
fcntl fail : Resource temporarily unavailable
所以,加鎖是成功的。
?
評(píng)論
查看更多