fcntl实现【文件区锁定】,【区锁定测试】,【区域锁定竞争】程序
2015-06-28 10:22
591 查看
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> 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);//给文件描述符写一个字节的A } /* 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;//第一个字节是40 region_2.l_len = 10;//这个区域的长度是10 /* now lock the file */ printf("Process %d locking file\n", getpid()); res = fcntl(file_desc, F_SETLK, ®ion_1);//对文件描述符,设置文件锁,在指向flock结构的指针region_1处 if (res == -1) fprintf(stderr, "Failed to lock region 1\n");//失败返回-1 res = fcntl(file_desc, F_SETLK, ®ion_2);//对文件描述符,设置文件锁,在指向flock结构的指针region_2处 if (res == -1) fprintf(stderr, "Failed to lock region 2\n"); //失败返回-1 /* and wait for a while */ sleep(60);//等待一分钟 printf("Process %d closing file\n", getpid()); close(file_desc); exit(EXIT_SUCCESS); } /* 00---------- 10----------<---- F_RDCLK共享锁 30----------<---- 40----------<---- F_WTCLK独占锁 50----------<---- 90---------- 100--------- */
上面的代码设置10-30字节上为读锁也就是共享锁,在40-50区域设置的是写锁也就是独占锁,下面是测试程序:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> const char *test_file = "/tmp/test_lock";//创建一个字符串常量指针指向临时文件 #define SIZE_TO_TRY 5 //宏定义一个常量 void show_lock_info(struct flock *to_show);//定义函数的格式 int main() { //主函数 int file_desc; int res; struct flock region_to_test;//定义flock结构 int start_byte; /* open a file descriptor */ file_desc = open(test_file, O_RDWR | O_CREAT, 0666);//按照指定的格式打开一个文件描述符给file_desc 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;//第一个字节: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);//测试的区域,0-5,5-10,...,95-100 /* 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) {//设定测试区域失败,也就是如果测试区域的记录带锁进程不是-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;//第一个字节: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 *///大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); }
上面的测试程序是按照5个字节为单位测试整个区域,打印出测试的结果。
【第一个点】上面的l_pid设置为-1是一个非法值,但是要是测试区域没被锁定,不会修改这个值,要是被锁定的话,这个值会被修改,打印处相应的信息。
下面是执行的结果
jason@t61:~/c_program/544977-blp3e/chapter07$ ./lock3 & [1] 4903 jason@t61:~/c_program/544977-blp3e/chapter07$ Process 4903 locking file ./lock4 Testing F_WRLCK on region from 0 to 5 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 0 to 5 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 5 to 10 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 5 to 10 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 10 to 15 Lock would fail. F_GETLK returned: l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 Testing F_RDLCK on region from 10 to 15 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 15 to 20 Lock would fail. F_GETLK returned: l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 Testing F_RDLCK on region from 15 to 20 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 20 to 25 Lock would fail. F_GETLK returned: l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 Testing F_RDLCK on region from 20 to 25 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 25 to 30 Lock would fail. F_GETLK returned: l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 Testing F_RDLCK on region from 25 to 30 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 30 to 35 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 30 to 35 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 35 to 40 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 35 to 40 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 40 to 45 Lock would fail. F_GETLK returned: l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 Testing F_RDLCK on region from 40 to 45 Lock would fail. F_GETLK returned: l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 Testing F_WRLCK on region from 45 to 50 Lock would fail. F_GETLK returned: l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 Testing F_RDLCK on region from 45 to 50 Lock would fail. F_GETLK returned: l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 Testing F_WRLCK on region from 50 to 55 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 50 to 55 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 55 to 60 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 55 to 60 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 60 to 65 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 60 to 65 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 65 to 70 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 65 to 70 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 70 to 75 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 70 to 75 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 75 to 80 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 75 to 80 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 80 to 85 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 80 to 85 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 85 to 90 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 85 to 90 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 90 to 95 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 90 to 95 F_RDLCK - Lock would succeed Testing F_WRLCK on region from 95 to 100 F_WRLCK - Lock would succeed Testing F_RDLCK on region from 95 to 100 F_RDLCK - Lock would succeed
可以看到,10-30字节,以前设定的是读锁,也就是共享锁,在这个区域的测试都是可以写共享锁,不能写独占锁,l_type值为0表示读锁存在。
40-50字节,以前设定的是写锁,也就是独占锁,在这个区域的测试都是失败的,l_type的值为1表示写锁存在。
其他的区域,也就是未被锁定的区域写任何锁都会成功。【这俩个测试是分别设置和分别执行的才可以不受相互之间的影响】
下面试图对锁定的区域进行锁的设置也就是竞争,看看发生什么事情
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> const char *test_file = "/tmp/test_lock"; int main() { int file_desc; struct flock region_to_lock; 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); } region_to_lock.l_type = F_RDLCK;//设定要锁定的区域及其格式 region_to_lock.l_whence = SEEK_SET;//就是10-15字节处为读(共享)锁 region_to_lock.l_start = 10; region_to_lock.l_len = 5; printf("Process %d, trying F_RDLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//区设置锁 if (res == -1) { printf("Process %d - failed to lock region\n", getpid());//失败处理 } else { printf("Process %d - obtained lock region\n", getpid());//成功处理 } region_to_lock.l_type = F_UNLCK;//设定一个区域区解锁 region_to_lock.l_whence = SEEK_SET;//还是10-15字节处 region_to_lock.l_start = 10; region_to_lock.l_len = 5; printf("Process %d, trying F_UNLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); res = fcntl(file_desc, F_SETLK, ®ion_to_lock); if (res == -1) { printf("Process %d - failed to unlock region\n", getpid());//失败处理 } else { printf("Process %d - unlocked region\n", getpid());//成功处理 } region_to_lock.l_type = F_UNLCK; region_to_lock.l_whence = SEEK_SET; region_to_lock.l_start = 0; region_to_lock.l_len = 50; printf("Process %d, trying F_UNLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//0-50设置解锁 if (res == -1) { printf("Process %d - failed to unlock region\n", getpid()); } else { printf("Process %d - unlocked region\n", getpid()); } region_to_lock.l_type = F_WRLCK; region_to_lock.l_whence = SEEK_SET; region_to_lock.l_start = 16; region_to_lock.l_len = 5; printf("Process %d, trying F_WRLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//16-21字节设置写锁 if (res == -1) { printf("Process %d - failed to lock region\n", getpid()); } else { printf("Process %d - obtained lock on region\n", getpid()); } region_to_lock.l_type = F_RDLCK; region_to_lock.l_whence = SEEK_SET; region_to_lock.l_start = 40; region_to_lock.l_len = 10; printf("Process %d, trying F_RDLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//40-50设置读锁 if (res == -1) { printf("Process %d - failed to lock region\n", getpid()); } else { printf("Process %d - obtained lock on region\n", getpid()); } region_to_lock.l_type = F_WRLCK; region_to_lock.l_whence = SEEK_SET; region_to_lock.l_start = 16; region_to_lock.l_len = 5; printf("Process %d, trying F_WRLCK with wait, region %d to %d\n", getpid(), (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); res = fcntl(file_desc, F_SETLKW, ®ion_to_lock);//16-21设置写锁无法设置的时候的等待直到可以为止 if (res == -1) { printf("Process %d - failed to lock region\n", getpid()); } else { printf("Process %d - obtained lock on region\n", getpid()); } printf("Process %d ending\n", getpid()); close(file_desc); exit(EXIT_SUCCESS); }
下面是这个程序的执行结果和分析:
ason@t61:~/c_program/544977-blp3e/chapter07$ gcc lock5.c -o lock5 jason@t61:~/c_program/544977-blp3e/chapter07$ ./lock3 & [1] 5091 jason@t61:~/c_program/544977-blp3e/chapter07$ Process 5091 locking file ./lock5 Process 5092, trying F_RDLCK, region 10 to 15//以前是读锁 Process 5092 - obtained lock region //设置读锁成功 Process 5092, trying F_UNLCK, region 10 to 15//以前是读锁 Process 5092 - unlocked region //解锁成功 Process 5092, trying F_UNLCK, region 0 to 50 //以前有读锁,有写锁,但是整个区域没有写锁定 Process 5092 - unlocked region //不是解锁成功,因为本身没锁 Process 5092, trying F_WRLCK, region 16 to 21//以前是读锁 Process 5092 - failed to lock region //试图设置写锁失败了 Process 5092, trying F_RDLCK, region 40 to 50//以前是写锁 Process 5092 - failed to lock region //试图设置读锁失败了【就是我在写就算读也不行这是独占】 Process 5092, trying F_WRLCK with wait, region 16 to 21//以前是读锁就是共享锁,试图设置区域为独占锁 Process 5091 closing file //这次是等待的方式进行的,等到读锁这片区域的Lock3程序 Process 5092 - obtained lock on region //关闭文件释放锁之后,进行锁定。 Process 5092 ending [1]+ 已完成 ./lock3 jason@t61:~/c_program/544977-blp3e/chapter07$
参考文献:
Linux程序设计 Neil Matthew 第七章 数据管理
//2015年06月28日 星期日 10时47分18秒
相关文章推荐
- 如何在CentOS 7中禁用IPv6
- CF 553A 组合DP
- jdk环境变量配置
- android 常用第三方包的代码混淆
- 记一次TcpListenOverflows报警解决过程
- J2ee环境安装与注意事项
- 如何在 Linux 中安装漂亮的 GTK+ 扁平化主题 Arc
- 如何在 Linux 中安装漂亮的 GTK+ 扁平化主题 Arc
- codeforces #309 D D. Nudist Beach(浮点数二分+bfs)
- Java 使用JDBC链接MySQL数据库(Linux)
- 机房重构之存储过程的使用
- puppet介绍及基于httpd实例部署
- markdownb编辑器
- shell awk入门
- Java中this关键字的几种用法(转)
- samb服务器最简单的共享设置方法
- Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效
- 浅谈hibernate save和saveOrUpdate区别
- 机械是个坑
- BMFont 使用方法 一