unix/linux 进程间文件锁

转自 http://www.cnblogs.com/hjslovewcl/archive/2011/03/14/2314333.html

有三种不同的文件锁,这三种都是“咨询性”的,也就是说它们依靠程序之间的
合作,所以一个项目中的所有程序封锁政策的一致是非常重要的,当你的程序需
要和第三方软件共享文件时应该格外地小心。

有 些程序利用诸如 FIlENAME.lock 的文件锁文件,然后简单地测试此类文件是否存在。这种方法显然不太好,因为当产生文件的进程被杀后,锁文件依然存在,这样文件也许会被永久锁住。UUCP 中把产生文件的进程号PID存入文件,但这样做仍然不保险,因为PID的利用是回收型的。

这里是三个文件锁函数:
     flock();
     lockf();
     fcntl();

flock()是从BSD中衍生出来的,但目前在大多数UNIX系统上都能找到,在单个主
机上flock()简单有效,但它不能在NFS上工作。Perl中也有一个有点让人迷惑的
flock()函数,但却是在perl内部实现的。

fcntl()是唯一的符合POSIX标准的文件锁实现,所以也是唯一可移植的。它也同
时是最强大的文件锁--也是最难用的。在NFS文件系统上,fcntl()请求会被递
交给叫rpc.lockd的守护进程,然后由它负责和主机端的lockd对话,和flock()
不同,fcntl()可以实现记录层上的封锁。

lockf()只是一个简化了的fcntl()文件锁接口。

无论你使用哪一种文件锁,请一定记住在锁生效之前用sync来更新你所有的文件
输入/输出。

  1. lock(fd);
  2. write_to(some_function_of(fd));
  3. flush_output_to(fd); /* 在去锁之前一定要冲洗输出 */
  4. unlock(fd);
  5. do_something_else;   /* 也许另外一个进程会更新它 */
  6. lock(fd);
  7. seek(fd, somewhere); /* 因为原来的文件指针已不安全 */
  8. do_something_with(fd); ...
  9. 一些有用的fcntl()封锁方法(为了简洁略去错误处理):
  10. #include <fcntl.h>;
  11. #include <unistd.h>;
  12. read_lock(int fd)   /* 整个文件上的一个共享的文件锁 */
  13. {
  14. fcntl(fd, F_SETLKW, file_lock(F_RDLCK, SEEK_SET));
  15. }
  16. write_lock(int fd)  /* 整个文件上的一个排外文件锁 */
  17. {
  18. fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
  19. }
  20. append_lock(int fd) /* 一个封锁文件结尾的锁,
  21. 其他进程可以访问现有内容 */
  22. {
  23. fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_END));
  24. }
  25. 前面所用的file_lock函数如下:
  26. struct flock* file_lock(short type, short whence)
  27. {
  28. static struct flock ret ;
  29. ret.l_type = type ;
  30. ret.l_start = 0 ;
  31. ret.l_whence = whence ;
  32. ret.l_len = 0 ;
  33. ret.l_pid = getpid() ;
  34. return &ret ;
  35. }
  1. //lock.c
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <string.h>
  6. struct flock* file_lock(short type, short whence)
  7. {
  8. static struct flock ret;
  9. ret.l_type = type ;
  10. ret.l_start = 0;
  11. ret.l_whence = whence;
  12. ret.l_len = 0;
  13. ret.l_pid = getpid();
  14. return &ret;
  15. }
  16. int main()
  17. {
  18. int fd = open("1.txt", O_WRONLY|O_APPEND);
  19. for(int i=0; i<1000; ++i) {
  20. fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
  21. char buf[1024] = {0};
  22. sprintf(buf, "hello world %d/n", i);
  23. int len = strlen(buf);
  24. write(fd, buf, len);
  25. fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
  26. sleep(1);
  27. }
  28. close(fd);
  29. }
  30. //lock2.c...同lock.c相比只是修改了下buf内容
  31. #include <stdio.h>
  32. #include <unistd.h>
  33. #include <fcntl.h>
  34. #include <string.h>
  35. struct flock* file_lock(short type, short whence)
  36. {
  37. static struct flock ret;
  38. ret.l_type = type ;
  39. ret.l_start = 0;
  40. ret.l_whence = whence;
  41. ret.l_len = 0;
  42. ret.l_pid = getpid();
  43. return &ret;
  44. }
  45. int main()
  46. {
  47. int fd = open("1.txt", O_WRONLY|O_APPEND);
  48. for(int i=0; i<1000; ++i) {
  49. fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
  50. char buf[1024] = {0};
  51. sprintf(buf, "china %d/n", i);
  52. int len = strlen(buf);
  53. write(fd, buf, len);
  54. fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
  55. sleep(1);
  56. }
  57. close(fd);
  58. }
  59. g++ lock.c -o 1
  60. g++ lock2.c -o 2
  61. 执行两个程序就能看到互斥的效果了
时间: 2024-08-26 00:48:11

unix/linux 进程间文件锁的相关文章

Linux/UNIX之进程间的通信(2)

进程间的通信(2) 有三种IPC我们称为XSI IPC,即消息队列.信号量以及共享存储器,它们之间有很多相似之处. 标识符和键 每个内核的IPC结构(消息队列.信号量或共享存储段)都用一个非负整数的标识符加以引用.例如,为了对一个消息队列发送或取消息,只需要知道其队列标识符.与文件描述符不同,IPC标识符不是小的整数.当一个IPC结构被创建,以后被删除时,与这种结果相关的标识符连续加1,知道达到一个整型数的最大值,然后又回到0. 标识符是IPC对象的内部名.为使多个合作进程能够在同一IPC对象上

Linux进程间的通信

一.管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: A. 管道是半双工的,数据只能向一个方向流动: B. 需要双工通信时,需要建立起两个管道: C. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): D. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 匿名管道的创建:该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义;因此,一

Linux进程间的通信方法

linux进程间的通信方法总结如下 通过fork函数把打开文件的描述符传递给子进程 通过wait得到子进程的终结信息 通过加锁的方式,实现几个进行共享读写某个文件 进行间通过信号通信,SIGUSR1和SIGUSR2实现用户定义功能 利用pipe进行通信 FIFO文件进行通信 mmap,几个进程映射到同一内存区 SYS IPC 消息队列,信号量(很少用) UNIX Domain Socket,常用

linux 进程间信号量管理程序之sem_timedwait使用

在开发过程中,有三个独立运行的程序模块,三个模块都对sqlite数据库进行读写操作.sqlite在linux共享性较差,所以需要加入互斥信号量解决三个模块访问数据库该问题.另外,在加入信号量后,信号量sem初始化为1,如果三个模块任意一个在读或写数据库时ctrl+c掉(调试过程需要),有时会造成信号量sem保持sem_wait后的值,也就是为0:这就造成了死锁. 为了解决上述情况,决定在某一个模块使用sem_timedwait(sem_t *sem,const struct timespec *

linux进程间通讯-System V IPC 信号量

进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在

Linux 进程间通讯方式 pipe()函数 (转载)

转自:http://blog.csdn.net/ta893115871/article/details/7478779 Linux 进程间通讯方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) 6->套接字(sicket) 在这里我们看一下第一种====管道(pipe).有名管道(fifo)见其它文章. eg :我们以前学的命令 cat  file | grep  "abc

linux 进程间的通信

现在linux使用的进程间通信方式:(1)管道(pipe)和有名管道(FIFO)(2)信号(signal)(3)消息队列(4)共享内存(5)信号量(6)套接字(socket) 为何进行进程间的通信:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到.C.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程).D.资源共享

linux进程间的通信(C): 消息队列

一.消息队列(message queue) 消息队列也是System V IPC机制之一. 消息队列与命名管道类似, 但少了打开和关闭管道方面的复杂性. 但使用消息队列并未解决我们在使用命名管道时遇到的一些问题, 如管道满时的阻塞问题. 消息队列提供了一种在两个不相关进程间传递数据的简单有效的方法. 与命名管道相比, 消息队列的优势在于,它独立于发送和接收进程而存在, 这消除了在同步命名管道的打开和关闭时可能产生的一些困难. 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 而且,

Linux 进程间通讯详解一

进程间的通讯 两台主机间的进程通讯 --socket 一台主机间的进程通讯 --管道(匿名管道,有名管道) --System V进程间通信(IPC)包括System V消息队列,System V信号量,System V共享内存 --socket 进程间共享内存的三种方式 --文件系统(通过系统调用读写磁盘文件,scoket)==>最慢 --Linux内核共享信息(直接在Linux内核中1进行通讯,比如管道,消息队列,信号)==>中等 --共享内存区(在自己进程内开辟一块内存,映射到系统内存)=