我是靠谱客的博主 愤怒百合,最近开发中收集的这篇文章主要介绍fcntl实现【文件区锁定】,【区锁定测试】,【区域锁定竞争】程序,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 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, &region_1);//对文件描述符,设置文件锁,在指向flock结构的指针region_1处
46
if (res == -1) fprintf(stderr, "Failed to lock region 1n");//失败返回-1
47
res = fcntl(file_desc, F_SETLK, &region_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, &region_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(&region_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, &region_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(&region_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, &region_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, &region_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, &region_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, &region_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, &region_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, &region_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实现【文件区锁定】,【区锁定测试】,【区域锁定竞争】程序所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部