概述
1 #include <unistd.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 6 const char *test_file = "/tmp/test_lock";//创建一个字符串常量指针指向临时文件 7 8 int main() 9 { 10 int file_desc; 11 int byte_count; 12 char *byte_to_write = "A"; 13 struct flock region_1; 14 struct flock region_2; 15 int res; 16 17 /* open a file descriptor */ 18 file_desc = open(test_file, O_RDWR | O_CREAT, 0666);//指定的权限打开一个文件获得一个文件描述符 19 if (!file_desc) 20 { 21 fprintf(stderr, "Unable to open %s for read/writen", test_file);//失败打印这句话 22 exit(EXIT_FAILURE); 23 } 24 25 /* put some data in the file */ 26 for(byte_count = 0; byte_count < 100; byte_count++) 27 {//循环 28 (void)write(file_desc, byte_to_write, 1);//给文件描述符写一个字节的A 29 } 30 31 /* setup region 1, a shared lock, from bytes 10 -> 30 */ 32 region_1.l_type = F_RDLCK;//共享锁 33 region_1.l_whence = SEEK_SET;//文件头开始 34 region_1.l_start = 10;//第一个字节 35 region_1.l_len = 20; //这个区域的字节数 36 37 /* setup region 2, an exclusive lock, from bytes 40 -> 50 */ 38 region_2.l_type = F_WRLCK;//独占锁 39 region_2.l_whence = SEEK_SET;//文件头开始 40 region_2.l_start = 40;//第一个字节是40 41 region_2.l_len = 10;//这个区域的长度是10 42 43 /* now lock the file */ 44 printf("Process %d locking filen", getpid()); 45 res = fcntl(file_desc, F_SETLK, ®ion_1);//对文件描述符,设置文件锁,在指向flock结构的指针region_1处 46 if (res == -1) fprintf(stderr, "Failed to lock region 1n");//失败返回-1 47 res = fcntl(file_desc, F_SETLK, ®ion_2);//对文件描述符,设置文件锁,在指向flock结构的指针region_2处 48 if (res == -1) fprintf(stderr, "Failed to lock region 2n"); //失败返回-1 49 50 /* and wait for a while */ 51 sleep(60);//等待一分钟 52 53 printf("Process %d closing filen", getpid()); 54 close(file_desc); 55 exit(EXIT_SUCCESS); 56 } 57 58 59 /* 60 00---------- 61 62 10----------<---- 63 64 F_RDCLK共享锁 65 66 30----------<---- 67 68 40----------<---- 69 F_WTCLK独占锁 70 50----------<---- 71 72 73 74 75 76 77 78 79 90---------- 80 81 82 100--------- 83 84 */
上面的代码设置10-30字节上为读锁也就是共享锁,在40-50区域设置的是写锁也就是独占锁,下面是测试程序:
1 #include <unistd.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 6 7 const char *test_file = "/tmp/test_lock";//创建一个字符串常量指针指向临时文件 8 #define SIZE_TO_TRY 5 //宏定义一个常量 9 10 void show_lock_info(struct flock *to_show);//定义函数的格式 11 12 13 int main() { //主函数 14 int file_desc; 15 int res; 16 struct flock region_to_test;//定义flock结构 17 int start_byte; 18 19 /* open a file descriptor */ 20 file_desc = open(test_file, O_RDWR | O_CREAT, 0666);//按照指定的格式打开一个文件描述符给file_desc 21 if (!file_desc) { 22 fprintf(stderr, "Unable to open %s for read/write", test_file); 23 exit(EXIT_FAILURE); 24 } 25 26 for (start_byte = 0; start_byte < 99; start_byte += SIZE_TO_TRY) 27 {//设定循环格式 28 /* set up the region we wish to test *///设定测试区域 29 region_to_test.l_type = F_WRLCK;//独占锁 30 region_to_test.l_whence = SEEK_SET;//区域:从文件头 31 region_to_test.l_start = start_byte;//第一个字节:start_byte 32 region_to_test.l_len = SIZE_TO_TRY;//区域的字节数 33 region_to_test.l_pid = -1; //记录带锁进程 34 35 printf("Testing F_WRLCK on region from %d to %dn", //首先打印一句话 36 start_byte, start_byte + SIZE_TO_TRY);//测试的区域,0-5,5-10,...,95-100 37 38 /* now test the lock on the file */ 39 res = fcntl(file_desc, F_GETLK, ®ion_to_test);//获得指定描述符的文件的锁信息, 40 if (res == -1) { 41 fprintf(stderr, "F_GETLK failedn"); 42 exit(EXIT_FAILURE); 43 }//文件打开成功的话继续执行 44 if (region_to_test.l_pid != -1) {//设定测试区域失败,也就是如果测试区域的记录带锁进程不是-1 45 printf("Lock would fail. F_GETLK returned:n"); 46 show_lock_info(®ion_to_test);//打印出获得的区域的锁描述 47 } 48 else { 49 printf("F_WRLCK - Lock would succeedn");//成功的话就是设定独占锁成功 50 } 51 52 /* now repeat the test with a shared (read) lock */ 53 54 /* set up the region we wish to test */ 55 region_to_test.l_type = F_RDLCK;//设定测试区域为共享锁 56 region_to_test.l_whence = SEEK_SET;//区域的开始从文件头 57 region_to_test.l_start = start_byte;//第一个字节:start_byte 58 region_to_test.l_len = SIZE_TO_TRY;//区域的字节数 59 region_to_test.l_pid = -1; 60 61 printf("Testing F_RDLCK on region from %d to %dn", 62 start_byte, start_byte + SIZE_TO_TRY); 63 64 /* now test the lock on the file */ 65 res = fcntl(file_desc, F_GETLK, ®ion_to_test); 66 if (res == -1) { 67 fprintf(stderr, "F_GETLK failedn"); 68 exit(EXIT_FAILURE); 69 } 70 if (region_to_test.l_pid != -1) { 71 printf("Lock would fail. F_GETLK returned:n"); 72 show_lock_info(®ion_to_test); 73 } 74 else {//获取文件锁状态和设置区域锁都成功的话,执行打印 75 printf("F_RDLCK - Lock would succeedn"); 76 } 77 78 } /* for *///大for循环结束 79 80 close(file_desc); 81 exit(EXIT_SUCCESS); 82 } 83 84 void show_lock_info(struct flock *to_show) { 85 printf("tl_type %d, ", to_show->l_type); 86 printf("l_whence %d, ", to_show->l_whence); 87 printf("l_start %d, ", (int)to_show->l_start); 88 printf("l_len %d, ", (int)to_show->l_len); 89 printf("l_pid %dn", to_show->l_pid); 90 }
上面的测试程序是按照5个字节为单位测试整个区域,打印出测试的结果。
【第一个点】上面的l_pid设置为-1是一个非法值,但是要是测试区域没被锁定,不会修改这个值,要是被锁定的话,这个值会被修改,打印处相应的信息。
下面是执行的结果
1 jason@t61:~/c_program/544977-blp3e/chapter07$ ./lock3 & 2 [1] 4903 3 jason@t61:~/c_program/544977-blp3e/chapter07$ Process 4903 locking file 4 ./lock4 5 Testing F_WRLCK on region from 0 to 5 6 F_WRLCK - Lock would succeed 7 Testing F_RDLCK on region from 0 to 5 8 F_RDLCK - Lock would succeed 9 Testing F_WRLCK on region from 5 to 10 10 F_WRLCK - Lock would succeed 11 Testing F_RDLCK on region from 5 to 10 12 F_RDLCK - Lock would succeed 13 Testing F_WRLCK on region from 10 to 15 14 Lock would fail. F_GETLK returned: 15 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 16 Testing F_RDLCK on region from 10 to 15 17 F_RDLCK - Lock would succeed 18 Testing F_WRLCK on region from 15 to 20 19 Lock would fail. F_GETLK returned: 20 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 21 Testing F_RDLCK on region from 15 to 20 22 F_RDLCK - Lock would succeed 23 Testing F_WRLCK on region from 20 to 25 24 Lock would fail. F_GETLK returned: 25 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 26 Testing F_RDLCK on region from 20 to 25 27 F_RDLCK - Lock would succeed 28 Testing F_WRLCK on region from 25 to 30 29 Lock would fail. F_GETLK returned: 30 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 4903 31 Testing F_RDLCK on region from 25 to 30 32 F_RDLCK - Lock would succeed 33 Testing F_WRLCK on region from 30 to 35 34 F_WRLCK - Lock would succeed 35 Testing F_RDLCK on region from 30 to 35 36 F_RDLCK - Lock would succeed 37 Testing F_WRLCK on region from 35 to 40 38 F_WRLCK - Lock would succeed 39 Testing F_RDLCK on region from 35 to 40 40 F_RDLCK - Lock would succeed 41 Testing F_WRLCK on region from 40 to 45 42 Lock would fail. F_GETLK returned: 43 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 44 Testing F_RDLCK on region from 40 to 45 45 Lock would fail. F_GETLK returned: 46 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 47 Testing F_WRLCK on region from 45 to 50 48 Lock would fail. F_GETLK returned: 49 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 50 Testing F_RDLCK on region from 45 to 50 51 Lock would fail. F_GETLK returned: 52 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 4903 53 Testing F_WRLCK on region from 50 to 55 54 F_WRLCK - Lock would succeed 55 Testing F_RDLCK on region from 50 to 55 56 F_RDLCK - Lock would succeed 57 Testing F_WRLCK on region from 55 to 60 58 F_WRLCK - Lock would succeed 59 Testing F_RDLCK on region from 55 to 60 60 F_RDLCK - Lock would succeed 61 Testing F_WRLCK on region from 60 to 65 62 F_WRLCK - Lock would succeed 63 Testing F_RDLCK on region from 60 to 65 64 F_RDLCK - Lock would succeed 65 Testing F_WRLCK on region from 65 to 70 66 F_WRLCK - Lock would succeed 67 Testing F_RDLCK on region from 65 to 70 68 F_RDLCK - Lock would succeed 69 Testing F_WRLCK on region from 70 to 75 70 F_WRLCK - Lock would succeed 71 Testing F_RDLCK on region from 70 to 75 72 F_RDLCK - Lock would succeed 73 Testing F_WRLCK on region from 75 to 80 74 F_WRLCK - Lock would succeed 75 Testing F_RDLCK on region from 75 to 80 76 F_RDLCK - Lock would succeed 77 Testing F_WRLCK on region from 80 to 85 78 F_WRLCK - Lock would succeed 79 Testing F_RDLCK on region from 80 to 85 80 F_RDLCK - Lock would succeed 81 Testing F_WRLCK on region from 85 to 90 82 F_WRLCK - Lock would succeed 83 Testing F_RDLCK on region from 85 to 90 84 F_RDLCK - Lock would succeed 85 Testing F_WRLCK on region from 90 to 95 86 F_WRLCK - Lock would succeed 87 Testing F_RDLCK on region from 90 to 95 88 F_RDLCK - Lock would succeed 89 Testing F_WRLCK on region from 95 to 100 90 F_WRLCK - Lock would succeed 91 Testing F_RDLCK on region from 95 to 100 92 F_RDLCK - Lock would succeed
可以看到,10-30字节,以前设定的是读锁,也就是共享锁,在这个区域的测试都是可以写共享锁,不能写独占锁,l_type值为0表示读锁存在。
40-50字节,以前设定的是写锁,也就是独占锁,在这个区域的测试都是失败的,l_type的值为1表示写锁存在。
其他的区域,也就是未被锁定的区域写任何锁都会成功。【这俩个测试是分别设置和分别执行的才可以不受相互之间的影响】
下面试图对锁定的区域进行锁的设置也就是竞争,看看发生什么事情
1 #include <unistd.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 6 7 const char *test_file = "/tmp/test_lock"; 8 9 int main() 10 { 11 int file_desc; 12 struct flock region_to_lock; 13 int res; 14 15 /* open a file descriptor */ 16 file_desc = open(test_file, O_RDWR | O_CREAT, 0666);//打开文件描述符 17 if (!file_desc) 18 { 19 fprintf(stderr, "Unable to open %s for read/writen", test_file); 20 exit(EXIT_FAILURE); 21 } 22 23 region_to_lock.l_type = F_RDLCK;//设定要锁定的区域及其格式 24 region_to_lock.l_whence = SEEK_SET;//就是10-15字节处为读(共享)锁 25 region_to_lock.l_start = 10; 26 region_to_lock.l_len = 5; 27 printf("Process %d, trying F_RDLCK, region %d to %dn", getpid(), 28 (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); 29 res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//区设置锁 30 if (res == -1) { 31 printf("Process %d - failed to lock regionn", getpid());//失败处理 32 } else { 33 printf("Process %d - obtained lock regionn", getpid());//成功处理 34 } 35 36 region_to_lock.l_type = F_UNLCK;//设定一个区域区解锁 37 region_to_lock.l_whence = SEEK_SET;//还是10-15字节处 38 region_to_lock.l_start = 10; 39 region_to_lock.l_len = 5; 40 printf("Process %d, trying F_UNLCK, region %d to %dn", getpid(), 41 (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); 42 res = fcntl(file_desc, F_SETLK, ®ion_to_lock); 43 if (res == -1) { 44 printf("Process %d - failed to unlock regionn", getpid());//失败处理 45 } else { 46 printf("Process %d - unlocked regionn", getpid());//成功处理 47 } 48 49 region_to_lock.l_type = F_UNLCK; 50 region_to_lock.l_whence = SEEK_SET; 51 region_to_lock.l_start = 0; 52 region_to_lock.l_len = 50; 53 printf("Process %d, trying F_UNLCK, region %d to %dn", getpid(), 54 (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); 55 res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//0-50设置解锁 56 if (res == -1) { 57 printf("Process %d - failed to unlock regionn", getpid()); 58 } else { 59 printf("Process %d - unlocked regionn", getpid()); 60 } 61 62 region_to_lock.l_type = F_WRLCK; 63 region_to_lock.l_whence = SEEK_SET; 64 region_to_lock.l_start = 16; 65 region_to_lock.l_len = 5; 66 printf("Process %d, trying F_WRLCK, region %d to %dn", getpid(), 67 (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); 68 res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//16-21字节设置写锁 69 if (res == -1) { 70 printf("Process %d - failed to lock regionn", getpid()); 71 } else { 72 printf("Process %d - obtained lock on regionn", getpid()); 73 } 74 75 region_to_lock.l_type = F_RDLCK; 76 region_to_lock.l_whence = SEEK_SET; 77 region_to_lock.l_start = 40; 78 region_to_lock.l_len = 10; 79 printf("Process %d, trying F_RDLCK, region %d to %dn", getpid(), 80 (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); 81 res = fcntl(file_desc, F_SETLK, ®ion_to_lock);//40-50设置读锁 82 if (res == -1) { 83 printf("Process %d - failed to lock regionn", getpid()); 84 } else { 85 printf("Process %d - obtained lock on regionn", getpid()); 86 } 87 88 region_to_lock.l_type = F_WRLCK; 89 region_to_lock.l_whence = SEEK_SET; 90 region_to_lock.l_start = 16; 91 region_to_lock.l_len = 5; 92 printf("Process %d, trying F_WRLCK with wait, region %d to %dn", getpid(), 93 (int)region_to_lock.l_start, (int)(region_to_lock.l_start + region_to_lock.l_len)); 94 res = fcntl(file_desc, F_SETLKW, ®ion_to_lock);//16-21设置写锁无法设置的时候的等待直到可以为止 95 if (res == -1) { 96 printf("Process %d - failed to lock regionn", getpid()); 97 } else { 98 printf("Process %d - obtained lock on regionn", getpid()); 99 } 100 101 printf("Process %d endingn", getpid()); 102 close(file_desc); 103 exit(EXIT_SUCCESS); 104 }
下面是这个程序的执行结果和分析:
1 ason@t61:~/c_program/544977-blp3e/chapter07$ gcc lock5.c -o lock5 2 jason@t61:~/c_program/544977-blp3e/chapter07$ ./lock3 & 3 [1] 5091 4 jason@t61:~/c_program/544977-blp3e/chapter07$ Process 5091 locking file 5 ./lock5 6 Process 5092, trying F_RDLCK, region 10 to 15//以前是读锁 7 Process 5092 - obtained lock region //设置读锁成功 8 Process 5092, trying F_UNLCK, region 10 to 15//以前是读锁 9 Process 5092 - unlocked region //解锁成功 10 Process 5092, trying F_UNLCK, region 0 to 50 //以前有读锁,有写锁,但是整个区域没有写锁定 11 Process 5092 - unlocked region //不是解锁成功,因为本身没锁 12 Process 5092, trying F_WRLCK, region 16 to 21//以前是读锁 13 Process 5092 - failed to lock region //试图设置写锁失败了 14 Process 5092, trying F_RDLCK, region 40 to 50//以前是写锁 15 Process 5092 - failed to lock region //试图设置读锁失败了【就是我在写就算读也不行这是独占】 16 Process 5092, trying F_WRLCK with wait, region 16 to 21//以前是读锁就是共享锁,试图设置区域为独占锁 17 Process 5091 closing file //这次是等待的方式进行的,等到读锁这片区域的Lock3程序 18 Process 5092 - obtained lock on region //关闭文件释放锁之后,进行锁定。 19 Process 5092 ending 20 [1]+ 已完成 ./lock3 21 jason@t61:~/c_program/544977-blp3e/chapter07$
参考文献:
Linux程序设计 Neil Matthew 第七章 数据管理
//2015年06月28日 星期日 10时47分18秒
转载于:https://www.cnblogs.com/kongchung/p/4605169.html
最后
以上就是愤怒百合为你收集整理的fcntl实现【文件区锁定】,【区锁定测试】,【区域锁定竞争】程序的全部内容,希望文章能够帮你解决fcntl实现【文件区锁定】,【区锁定测试】,【区域锁定竞争】程序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复