Linux应用程序之文件锁操作

来源:互联网 发布:jade软件339 编辑:程序博客网 时间:2024/06/05 16:23

Linux下文件锁操作主要是通过以下两个API接口来完成的。

#include <sys/file.h>int flock(int fd, int operation);  

或者

#include <unistd.h>#include <fcntl.h>int fcntl(int fd, int cmd);int fcntl(int fd, int cmd, long arg);int fcntl(int fd, int cmd, struct flock *lock);
注:前者主要用于对整个文件的锁操作,后者可以对文件的部分内容进行锁操作。


Linux应用程序编程时应该注意以下几点:

1)文件锁是针对整个文件还是文件的部分内容。

2)进程级文件句柄关闭将会导致文件锁释放。

3)文件内容修改需要注意到glibc的缓冲机制,及时同步数据。

4)flock锁inode,fcntl锁文件描述符,因此flock不支持NFS,兼容性需要注意。

这里将给出进程级和线程级文件锁demo code供参考。

进程级文件锁demo:

#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#define TEST_FOPENint main(int argc, char *argv[]){    /* l_type   l_whence  l_start  l_len  l_pid   */    struct flock fl = {F_WRLCK, SEEK_SET,   0,      0,     0 };    int fd;#ifdef TEST_FOPENFILE *file = NULL;#endif /* TEST_FOPEN */    fl.l_pid = getpid();    if (argc > 1)        fl.l_type = F_RDLCK;while(1){#ifdef TEST_FOPEN    if ((file = fopen("lockdemo.c", "rw+")) == NULL) {        perror("fopen");        exit(1);    }#else    if ((fd = open("lockdemo.c", O_RDWR)) == -1) {        perror("open");        exit(1);    }#endif /* TEST_FOPEN */printf("Press <RETURN> to try to get lock: ");getchar();printf("Trying to get lock...");#ifdef TEST_FOPENfd = fileno(file);#endif /* TEST_FOPEN */fl.l_type = F_WRLCK;  /* set to lock same region */if (fcntl(fd, F_SETLKW, &fl) == -1) {perror("fcntl");exit(1);}printf("got lock\n");printf("Press <RETURN> to release lock: ");getchar();fl.l_type = F_UNLCK;  /* set to unlock same region */if (fcntl(fd, F_SETLK, &fl) == -1) {perror("fcntl");exit(1);}printf("Unlocked.\n");#ifdef TEST_FOPENfclose(file);#else    close(fd);#endif /* TEST_FOPEN */}    return 0;}
运行结果:



线程级文件锁demo:

#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <pthread.h>#define TEST_FOPEN#define TEST_FLOCKvoid* thread_flock(void* ptr){    /* l_type   l_whence  l_start  l_len  l_pid   */    struct flock fl = {F_WRLCK, SEEK_SET,   0,      0,     0 };    int fd;int ith = *((int *)ptr);#ifdef TEST_FOPENFILE *file = NULL;#endif /* TEST_FOPEN */    fl.l_pid = getpid();while(1){#ifdef TEST_FOPEN    if ((file = fopen("lockdemo.c", "rw+")) == NULL) {        perror("fopen");        exit(1);    }#else    if ((fd = open("lockdemo.c", O_RDWR)) == -1) {        perror("open");        exit(1);    }#endif /* TEST_FOPEN */#ifdef TEST_FOPENfd = fileno(file);#endif /* TEST_FOPEN */#ifdef TEST_FLOCKflock(fd, LOCK_EX);#elsefl.l_type = F_WRLCK;  /* set to lock same region */if (fcntl(fd, F_SETLKW, &fl) == -1) {perror("fcntl");exit(1);}#endif /* TEST_FLOCK */printf("[%d] %d --> got lock\n", ith, fd);sleep(ith);#ifdef TEST_FLOCKflock(fd, LOCK_UN);#elsefl.l_type = F_UNLCK;  /* set to unlock same region */if (fcntl(fd, F_SETLKW, &fl) == -1) {perror("fcntl");exit(1);}#endif /* TEST_FLOCK */printf("[%d] %d--> Unlocked.\n", ith, fd);#ifdef TEST_FOPENfclose(file);#else    close(fd);#endif /* TEST_FOPEN */sleep(2);}}int main(int argc, char *argv[]){int time1, time2;pthread_t pid1,pid2;time1 = 1;pthread_create(&pid1, NULL, &thread_flock, &time1);time2 = 3;pthread_create(&pid2, NULL, &thread_flock, &time2);while(1)sleep(10);    return 0;}
运行结果:


参考资料:

【1】Linux man pages

【2】fcntl() for thread or process synchronization?

【3】How to lock files using fcntl() and to work between threads of the same process

【4】fcntl+pthread_rwlock制作的支持多进程多线程混合的互斥锁

【5】flock不支持NFS

【6】Re: Linux, fcntl vs flock and pthreads

原创粉丝点击