Linux应用程序之文件锁操作

http://blog.csdn.net/lida2003/article/details/7267226

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

[cpp] view plain copy print ?
  1. #include <sys/file.h>   
  2. int flock(int fd, int operation);    

或者

[cpp] view plain copy print ?
  1. #include <unistd.h>   
  2. #include <fcntl.h>   
  3. int fcntl(int fd, int cmd);  
  4. int fcntl(int fd, int cmd, long arg);  
  5. int fcntl(int fd, int cmd, struct flock *lock);  
注:前者主要用于对整个文件的锁操作,后者可以对文件的部分内容进行锁操作。


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

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

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

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

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

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

进程级文件锁demo:

[cpp] view plain copy print ?
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <errno.h>   
  4. #include <fcntl.h>   
  5. #include <unistd.h>   
  6.   
  7. #define TEST_FOPEN   
  8.   
  9. int main(int argc, char *argv[])  
  10. {  
  11.     /* l_type   l_whence  l_start  l_len  l_pid   */  
  12.     struct flock fl = {F_WRLCK, SEEK_SET,   0,      0,     0 };  
  13.     int fd;  
  14.   
  15. #ifdef TEST_FOPEN   
  16.     FILE *file = NULL;  
  17. #endif /* TEST_FOPEN */   
  18.   
  19.     fl.l_pid = getpid();  
  20.   
  21.     if (argc > 1)  
  22.         fl.l_type = F_RDLCK;  
  23.   
  24.     while(1)  
  25.     {  
  26. #ifdef TEST_FOPEN   
  27.     if ((file = fopen("lockdemo.c""rw+")) == NULL) {  
  28.         perror("fopen");  
  29.         exit(1);  
  30.     }  
  31. #else   
  32.     if ((fd = open("lockdemo.c", O_RDWR)) == -1) {  
  33.         perror("open");  
  34.         exit(1);  
  35.     }  
  36. #endif /* TEST_FOPEN */   
  37.         printf("Press <RETURN> to try to get lock: ");  
  38.         getchar();  
  39.         printf("Trying to get lock...");  
  40.   
  41.     #ifdef TEST_FOPEN   
  42.         fd = fileno(file);  
  43.     #endif /* TEST_FOPEN */  
  44.   
  45.         fl.l_type = F_WRLCK;  /* set to lock same region */  
  46.         if (fcntl(fd, F_SETLKW, &fl) == -1) {  
  47.             perror("fcntl");  
  48.             exit(1);  
  49.         }  
  50.   
  51.         printf("got lock\n");  
  52.         printf("Press <RETURN> to release lock: ");  
  53.         getchar();  
  54.   
  55.         fl.l_type = F_UNLCK;  /* set to unlock same region */  
  56.   
  57.         if (fcntl(fd, F_SETLK, &fl) == -1) {  
  58.             perror("fcntl");  
  59.             exit(1);  
  60.         }  
  61.   
  62.         printf("Unlocked.\n");  
  63. #ifdef TEST_FOPEN   
  64.     fclose(file);  
  65. #else   
  66.     close(fd);  
  67. #endif /* TEST_FOPEN */   
  68.     }  
  69.   
  70.     return 0;  
  71. }  
运行结果:



线程级文件锁demo:

[cpp] view plain copy print ?
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <errno.h>   
  4. #include <fcntl.h>   
  5. #include <unistd.h>   
  6. #include <pthread.h>   
  7.   
  8. #define TEST_FOPEN   
  9. #define TEST_FLOCK   
  10.   
  11. void* thread_flock(void* ptr)  
  12. {  
  13.     /* l_type   l_whence  l_start  l_len  l_pid   */  
  14.     struct flock fl = {F_WRLCK, SEEK_SET,   0,      0,     0 };  
  15.     int fd;  
  16.   
  17.     int ith = *((int *)ptr);  
  18.   
  19. #ifdef TEST_FOPEN   
  20.     FILE *file = NULL;  
  21. #endif /* TEST_FOPEN */   
  22.   
  23.     fl.l_pid = getpid();  
  24.   
  25.     while(1)  
  26.     {  
  27. #ifdef TEST_FOPEN   
  28.     if ((file = fopen("lockdemo.c""rw+")) == NULL) {  
  29.         perror("fopen");  
  30.         exit(1);  
  31.     }  
  32. #else   
  33.     if ((fd = open("lockdemo.c", O_RDWR)) == -1) {  
  34.         perror("open");  
  35.         exit(1);  
  36.     }  
  37. #endif /* TEST_FOPEN */   
  38.   
  39. #ifdef TEST_FOPEN   
  40.         fd = fileno(file);  
  41. #endif /* TEST_FOPEN */   
  42.   
  43. #ifdef TEST_FLOCK   
  44.         flock(fd, LOCK_EX);  
  45. #else   
  46.         fl.l_type = F_WRLCK;  /* set to lock same region */  
  47.         if (fcntl(fd, F_SETLKW, &fl) == -1) {  
  48.             perror("fcntl");  
  49.             exit(1);  
  50.         }  
  51. #endif /* TEST_FLOCK */   
  52.   
  53.         printf("[%d] %d --> got lock\n", ith, fd);  
  54.         sleep(ith);  
  55.   
  56. #ifdef TEST_FLOCK   
  57.         flock(fd, LOCK_UN);  
  58. #else   
  59.         fl.l_type = F_UNLCK;  /* set to unlock same region */  
  60.   
  61.         if (fcntl(fd, F_SETLKW, &fl) == -1) {  
  62.             perror("fcntl");  
  63.             exit(1);  
  64.         }  
  65. #endif /* TEST_FLOCK */   
  66.   
  67.         printf("[%d] %d--> Unlocked.\n", ith, fd);  
  68. #ifdef TEST_FOPEN   
  69.     fclose(file);  
  70. #else   
  71.     close(fd);  
  72. #endif /* TEST_FOPEN */   
  73.   
  74.         sleep(2);  
  75.     }  
  76. }  
  77.   
  78. int main(int argc, char *argv[])  
  79. {  
  80.     int time1, time2;  
  81.   
  82.     pthread_t pid1,pid2;  
  83.   
  84.     time1 = 1;  
  85.     pthread_create(&pid1, NULL, &thread_flock, &time1);  
  86.   
  87.     time2 = 3;  
  88.     pthread_create(&pid2, NULL, &thread_flock, &time2);  
  89.   
  90.     while(1)  
  91.         sleep(10);  
  92.   
  93.     return 0;  
  94. }  
运行结果:
Linux应用程序之文件锁操作_第1张图片


参考资料:

【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

 

你可能感兴趣的:(Linux应用程序之文件锁操作)