1. 程式人生 > >Linux記錄鎖(檔案鎖)

Linux記錄鎖(檔案鎖)

記錄鎖(record locking)的功能是:

當第一個程序正在讀或修改檔案的某個部分時,使用記錄鎖可以阻止其他程序修改同一檔案區。

“記錄”這個詞是一種誤用,因為UNIX系統核心根本沒有使用檔案記錄這種概念。

一個更適合的術語可能是位元組範圍鎖 (byte-range locking),因為它鎖定的只是檔案中的一個區域(也可能是整個檔案)。

struct flock {
             short l_type; /* 鎖型別: F_RDLCK, F_WRLCK, F_UNLCK */
             short l_whence; /* 取值為SEEK_SET(檔案頭), SEEK_CUR(檔案當前位置), SEEK_END(檔案尾) */
             off_t l_start; /* 相對於l_whence欄位的偏移量 */
             off_t l_len; /* 需要鎖定的長度 */
             pid_t l_pid; /* 當前獲得檔案鎖的程序標識(F_GETLK) */
};

例項程式碼:

#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <string.h>
//對檔案進行上鎖
#define read_lock(fd, offset, whence, len) \
	lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
#define readw_lock(fd, offset, whence, len) \
	lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
#define write_lock(fd, offset, whence, len) \
	lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
#define writew_lock(fd, offset, whence, len) \
	lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
#define un_lock(fd, offset, whence, len) \
	lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))
//判斷檔案能不能鎖
#define is_read_lockable(fd, offset, whence, len) \
	lock_test((fd), F_RDLCK, (offset), (whence), (len))
#define is_write_lockable(fd, offset, whence, len) \
	lock_test((fd), F_WRLCK, (offset), (whence), (len)) 

int
lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
	struct flock lock;
	int a = 852;
	lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */
	lock.l_start = offset; /* byte offset, relative to l_whence */
	lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
	lock.l_len = len; /* #bytes (0 means to EOF) */
	lock.l_pid = getpid();
	//printf("%d \n", lock.l_pid);	
	return(fcntl(fd, cmd, &lock));   
}
pid_t
lock_test(int fd, int type, off_t offset, int whence, off_t len)
{
	struct flock lock1;
	int a;
	lock1.l_type = type; /* F_RDLCK or F_WRLCK */
	lock1.l_start = offset; /* byte offset, relative to l_whence */
	lock1.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
	lock1.l_len = len; /* #bytes (0 means to EOF) */
	lock1.l_pid = getpid();

	if (fcntl(fd, F_GETLK, &lock1) < 0)
		perror("fcntl error");
	if (lock1.l_type == F_UNLCK)
	{				
		return(0); /* false, region isn’t locked by another proc */
	}
		
	return(lock1.l_pid); /* true, return pid of lock owner */
}
int
main(void)
{
	int i = -1;
	int j = -1;
	int fd = -1;
	int pid = -1;
	char buf[30] = {"this is  second\n"};
	
	if ( (fd = open("myfile", O_RDWR) ) < 0)
	{
		perror("open");
		exit(-1);
	}
	
	j = is_write_lockable(fd, 5, SEEK_SET, 1);  //判斷有沒有鎖
	if( j == 0 )
	{
		printf("thid file have no lock \n");
		printf("Now ,using file lock \n");
		write_lock(fd, 5, SEEK_SET, 1);  //上鎖
		for(;;);  //endless loop
	}else
	{
		printf("pid = %d using file lock\n", j);	//output using file lock Processes ID
	}
	exit(0);			
}

結果:

終端1:

# ./a.out  thid file have no lock  Now ,using file lock 

終端2:

# ps -au | grep a.out  root       9942  103  0.0   4200   352 pts/1    R+   09:25   0:13 ./a.out # ./a.out pid = 9942 using file lock