系统调用fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, struct flock *lock );
参数:
fd
:文件描述符
cmd
:F_GETLK, F_SETLK or F_SETLKW
lock
:按照如下规则填写,可以达到相应效果
F_GETLK, F_SETLK and F_SETLKW are used to acquire, release, and test for the existence of record locks (also known as file-segment or file-region
locks). The third argument, lock, is a pointer to a structure that has at least the following fields (in unspecified order).
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) */
...
};
文件锁的封装
filelock.h:
#ifndef _FILE_LOCK_H
#define _FILE_LOCK_H
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len);
int File_ReadLck(int fd, off_t offset, int whence, off_t len);
int File_WriteLck(int fd, off_t offset, int whence, off_t len);
int File_ReadLckW(int fd, off_t offset, int whence, off_t len);
int File_WriteLckW(int fd, off_t offset, int whence, off_t len);
int File_Unlock(int fd, off_t offset, int whence, off_t len);
#endif
filelock.c:
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include "filelock.h"
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
return (fcntl(fd, cmd, &lock));
}
int File_ReadLck(int fd, off_t offset, int whence, off_t len)
{
return lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len);
}
int File_WriteLck(int fd, off_t offset, int whence, off_t len)
{
return lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len);
}
int File_ReadLckW(int fd, off_t offset, int whence, off_t len)
{
return lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len);
}
int File_WriteLckW(int fd, off_t offset, int whence, off_t len)
{
return lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len);
}
int File_Unlock(int fd, off_t offset, int whence, off_t len)
{
return lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len);
}
例程
#include <stdio.h>
#include <fcntl.h>
#include "filelock.h"
int main(void)
{
int fd = 0;
pid_t pid = 0;
fd = open("tmp", O_RDWR|O_CREAT|O_TRUNC, 0666);
unlink("tmp");
pid = fork();
if(0 == pid)
{
while(1)
{
File_WriteLckW(fd, 0, SEEK_SET, 1);
printf("====> child process\n\n");
usleep(5000000);
File_Unlock(fd, 0, SEEK_SET, 1);
usleep(500000);
}
}
while(1)
{
File_WriteLckW(fd, 0, SEEK_SET, 1);
printf("#### parent process\n\n");
usleep(5000000);
File_Unlock(fd, 0, SEEK_SET, 1);
usleep(500000);
}
return 0;
}
文件锁的用法:
- 不同的对象访问同一文件,可以使用文件锁达到读写同步,不会导致文件写入混乱。
- 进程间访问同一资源,使用文件锁作为进程间的锁达到访问同步;
用法
:创建一个空文件,并使用文件的第一字节(无需存在)作为锁字节,然后unlink文件;获取资源之前,先获取该字节的写锁;释放资源时,对该字节解锁。记录锁的一个优点是:持有锁的进程终止退出时,内核会自动释放该锁,所以进程间就不会因为进程崩溃导致死锁。