加鎖兰迫、解鎖及測(cè)試代碼 lock.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <errno.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
/**
* @brief 嘗試獲取文件鎖
* @details 獲取文件鎖時(shí)不會(huì)阻塞進(jìn)程, 獲取不到鎖時(shí),立即返回不會(huì)等待
* @param fd 文件描述符
* @return 是否成功獲取文件鎖
* @retval TRUE 獲取鎖成功
* @retval FALSE 獲取鎖失敗
* @attention 這里只是建議性鎖憨降,每個(gè)使用上鎖文件的進(jìn)程都要檢查是否有鎖存在,
* 內(nèi)核不對(duì)讀寫操作做內(nèi)部檢查和強(qiáng)制保護(hù)
* @see ngx_trylock_fd
* @ref [http://agentzh.org/misc/code/nginx/os/unix/ngx_files.c.html#L416]
*/
int trylock_fd(int fd)
{
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &fl) == -1) {
return FALSE;
} else {
return TRUE;
}
}
/**
* @brief 獲取鎖或等待
* @details 獲取文件鎖時(shí)會(huì)阻塞進(jìn)程, 獲取不到鎖時(shí)担巩,一直等到獲取成功
* @param fd 文件描述符
* @return 是否成功獲取文件鎖
* @retval TRUE 獲取鎖成功
* @retval FALSE 獲取鎖失敗
* @attention 這里只是建議性鎖俩块,每個(gè)使用上鎖文件的進(jìn)程都要檢查是否有鎖存在,
* 內(nèi)核不對(duì)讀寫操作做內(nèi)部檢查和強(qiáng)制保護(hù)
* @see ngx_lock_fd
* @ref [http://agentzh.org/misc/code/nginx/os/unix/ngx_files.c.html#L433]
*/
int waitlock_fd(int fd)
{
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLKW, &fl) == -1) {
return FALSE;
} else {
return TRUE;
}
}
/**
* @brief 釋放文件鎖
* @param fd 文件描述符
* @return 是否成功釋放文件鎖
* @retval TRUE 釋放鎖成功
* @retval FALSE 釋放鎖失敗
* @see ngx_unlock_fd
* @ref [http://agentzh.org/misc/code/nginx/os/unix/ngx_files.c.html#L450]
*/
int unlock_fd(int fd)
{
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &fl) == -1) {
return FALSE;
} else {
return TRUE;
}
}
/**
* @brief 檢查是否設(shè)置了文件鎖
* @details 檢查文件鎖狀況欢揖,并輸出相關(guān)信息
* @param fd 文件描述符
*/
void checklock_fd(int fd)
{
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_GETLK, &fl) == -1) {
printf("failed to check file lock. detail: %s(%d)\n",
strerror(errno), errno);
return;
} else {
switch (fl.l_type) {
case F_UNLCK:
printf("no file lock\n");
break;
case F_RDLCK:
printf("read lock already set by %d\n", fl.l_pid);
break;
case F_WRLCK:
printf("write lock already set by %d\n", fl.l_pid);
break;
}
return;
}
}
/**
* @brief 主函數(shù)
* @details 測(cè)試獲取鎖陶耍、檢查鎖、釋放鎖的函數(shù)
* @param argc 命令參數(shù)個(gè)數(shù)
* @param argv 命令參數(shù)指針數(shù)組
* @return 程序執(zhí)行成功與否
* @retval 0 程序執(zhí)行成功
* @retval 1 程序執(zhí)行失敗
*/
int main(int argc, char *argv[])
{
int fd;
char *file;
pid_t pid;
if (argc == 2) {
file = argv[1];
} else {
file = "file.lock";
}
pid = getpid();
fd = open(file, O_RDWR|O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "failed to open \"%s\", detail: %s(%d)\n",
file, strerror(errno), errno);
exit(1);
}
if(trylock_fd(fd)) {
printf("file has been locked by %d. press any key to unlock\n", pid);
} else {
printf("waiting for lock\n");
checklock_fd(fd);
waitlock_fd(fd);
printf("file has been locked by %d. press any key to unlock\n", pid);
}
getchar();
unlock_fd(fd);
printf("file has been unlocked by %d.\n", pid);
close(fd);
exit(0);
}
編譯
# gcc lock.c -o lock
測(cè)試驗(yàn)證
窗口1
# ./lock
file has been locked by 3286. press any key to unlock
<-- 1) 按任意鍵她混,釋放鎖
file has been unlocked by 3286.
窗口2
# ./lock
waiting for lock
write lock already set by 3286
<-- 等待鎖釋放物臂,1)按下任意鍵后繼續(xù)
file has been locked by 3287. press any key to unlock
<-- 2) 按任意鍵旺拉,釋放鎖
file has been unlocked by 3287.