博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux文件锁定
阅读量:2439 次
发布时间:2019-05-10

本文共 5753 字,大约阅读时间需要 19 分钟。

    linux下文件锁定有两种:一种是以原子操作方式创建锁文件;另一种是允许锁定文件的一部分,从而独享对这一部分内容的访问。

    1、锁文件

    许多应用程序只需要能够针对某个资源创建一个锁文件,然后其他程序通过检查这个文件来判断它们是否被允许访问这个资源。创建锁文件使用fcntl.h头文件(楼主机器上位于/usr/include下)定义的open系统调用,并带上O_CREAT和O_EXCL标志。这样就以原子操作完成两项工作:确定文件不存在,然后    创建    

#include 
#include
#include
#include
#include
int main(){ int file_desc; int save_errno; file_desc = open("/tmp/LCK.test", O_RDWR | O_CREAT | O_EXCL, 0444); if (file_desc == -1) { save_errno = errno; printf("Open failed with error %d\n", save_errno); } else { printf("Open succeeded\n"); } exit(EXIT_SUCCESS);}
     不过在第二次运行以上程序的时候,会提示错误:open failed with error 17(文件已存在,错误码在/usr/include/asm-generic/error-base.h),如果想让程序再次执行成功,就必须删除那个锁文件。在c语言调用中,我们可以使用unlink函数(定义于/usr/include/unistd.h)。另外,以上的代码也不是很合理的,只有open没有close,正常情况下,应该加上以下两行:

(void)close(file_desc);            (void)unlink( "/tmp/LCK.test");
     关于unlink,可以参考 的说法。unlink原型如下:

#include 
int unlink (__const char *__name)
    函数功能:删除目录项,并将由__name所引用文件的链接
计数减1,当链接计数为0时,文件被删除。
    关于unlink的使用,可以参考《unix环境高级编程》第17章,17.3.2唯一链接,在listen前,先unlink以防文件已经存在,accept后再unlink,防止下次调用处问题。曾经楼主在ACE的unix域套接字ACE_LSOCK上遇到address in use,其实就是锁文件已存在没有删除的问题。

    

     2、区域锁定

    区域锁定出现,是因为锁文件方式并不适用于访问大型的共享文件。如果一个大文件,由一个程序写入数据,但却由不同的程序同时对这个文件进行更新。处理程序不能等待记录程序结束,所以需要一些协调方法来提供对同一个文件的并发访问。linux提供了2种方法来实现:一是fcntl系统调用和lockf调用。

    一个使用fcntl锁定文件的例子如下:

#include 
#include
#include
#include
const char *test_file = "/tmp/test_lock";int main() { int file_desc; int byte_count; char *byte_to_write = "A"; struct flock region_1; struct flock region_2; int res; /* open a file descriptor */ file_desc = open(test_file, O_RDWR | O_CREAT, 0666); if (!file_desc) { fprintf(stderr, "Unable to open %s for read/write\n", test_file); exit(EXIT_FAILURE); } /* put some data in the file */ for(byte_count = 0; byte_count < 100; byte_count++) { (void)write(file_desc, byte_to_write, 1); } /* setup region 1, a shared lock, from bytes 10 -> 30 */ region_1.l_type = F_RDLCK; region_1.l_whence = SEEK_SET; region_1.l_start = 10; region_1.l_len = 20; /* setup region 2, an exclusive lock, from bytes 40 -> 50 */ region_2.l_type = F_WRLCK; region_2.l_whence = SEEK_SET; region_2.l_start = 40; region_2.l_len = 10; /* now lock the file */ printf("Process %d locking file\n", getpid()); res = fcntl(file_desc, F_SETLK, ®ion_1); if (res == -1) fprintf(stderr, "Failed to lock region 1\n"); res = fcntl(file_desc, F_SETLK, ®ion_2); if (res == -1) fprintf(stderr, "Failed to lock region 2\n"); /* and wait for a while */ sleep(60); printf("Process %d closing file\n", getpid()); close(file_desc); exit(EXIT_SUCCESS);}
      程序首先创建一个文件,然后以读写方式打开,添加一些数据。接着在文件中设置2个区域,第一个是0-30,用读(共享)锁;第二个是40-50,用写(独占) 锁,然后调用fcntl来锁定这2个区域。
       fcntl参数提供了3个命令选项

       F_GETLK、F_SETLK、F_SETLKW,l_type提供的选项有F_RDLCK、F_UNLCK、F_WRLCK,分别为读锁,解锁,写锁

       测试锁的程序如下:

#include 
#include
#include
#include
const char *test_file = "/tmp/test_lock";#define SIZE_TO_TRY 5void show_lock_info(struct flock *to_show);int main() { int file_desc; int res; struct flock region_to_test; int start_byte; /* open a file descriptor */ file_desc = open(test_file, O_RDWR | O_CREAT, 0666); if (!file_desc) { fprintf(stderr, "Unable to open %s for read/write", test_file); exit(EXIT_FAILURE); } for (start_byte = 0; start_byte < 99; start_byte += SIZE_TO_TRY) { /* set up the region we wish to test */ region_to_test.l_type = F_WRLCK; region_to_test.l_whence = SEEK_SET; region_to_test.l_start = start_byte; region_to_test.l_len = SIZE_TO_TRY; region_to_test.l_pid = -1; printf("Testing F_WRLCK on region from %d to %d\n", start_byte, start_byte + SIZE_TO_TRY); /* now test the lock on the file */ res = fcntl(file_desc, F_GETLK, ®ion_to_test); if (res == -1) { fprintf(stderr, "F_GETLK failed\n"); exit(EXIT_FAILURE); } if (region_to_test.l_pid != -1) { printf("Lock would fail. F_GETLK returned:\n"); show_lock_info(®ion_to_test); } else { printf("F_WRLCK - Lock would succeed\n"); } /* now repeat the test with a shared (read) lock */ /* set up the region we wish to test */ region_to_test.l_type = F_RDLCK; region_to_test.l_whence = SEEK_SET; region_to_test.l_start = start_byte; region_to_test.l_len = SIZE_TO_TRY; region_to_test.l_pid = -1; printf("Testing F_RDLCK on region from %d to %d\n", start_byte, start_byte + SIZE_TO_TRY); /* now test the lock on the file */ res = fcntl(file_desc, F_GETLK, ®ion_to_test); if (res == -1) { fprintf(stderr, "F_GETLK failed\n"); exit(EXIT_FAILURE); } if (region_to_test.l_pid != -1) { printf("Lock would fail. F_GETLK returned:\n"); show_lock_info(®ion_to_test); } else { printf("F_RDLCK - Lock would succeed\n"); } } /* for */ close(file_desc); exit(EXIT_SUCCESS);}void show_lock_info(struct flock *to_show) { printf("\tl_type %d, ", to_show->l_type); printf("l_whence %d, ", to_show->l_whence); printf("l_start %d, ", (int)to_show->l_start); printf("l_len %d, ", (int)to_show->l_len); printf("l_pid %d\n", to_show->l_pid);}
(以上大部分内容来自《linux程序设计》)
     就是这样吧,遇到的东西是越来越多,慢慢总结

转载地址:http://zmcqb.baihongyu.com/

你可能感兴趣的文章
mern技术栈好处?_如何开始使用MERN堆栈
查看>>
路由器接路由器_路由器之战:到达路由器vsReact路由器
查看>>
rxjs 搜索_如何使用RxJS构建搜索栏
查看>>
如何在Debian 10上安装MariaDB
查看>>
go函数的可变长参数_如何在Go中使用可变参数函数
查看>>
react开源_React Icons让您可以访问数百个开源图标
查看>>
debian 服务器_使用Debian 10进行初始服务器设置
查看>>
joi 参数验证_使用Joi进行节点API架构验证
查看>>
react-notifications-component,一个强大的React Notifications库
查看>>
如何在Debian 10上设置SSH密钥
查看>>
如何在Debian 10上安装Node.js
查看>>
了解css_了解CSS的特异性
查看>>
emmet快速插入css_如何使用Emmet快速编写HTML
查看>>
graphql_GraphQL简介
查看>>
typescript 枚举_TypeScript枚举声明和合并
查看>>
flutter开发_加快Flutter开发的提示
查看>>
redis排序_如何在Redis中管理排序集
查看>>
使用Gatsby和Cosmic JS创建多语言网站
查看>>
redis 连接数据库_如何连接到Redis数据库
查看>>
如何在Ubuntu 18.04上对Redis服务器的性能进行基准测试
查看>>