zoukankan      html  css  js  c++  java
  • 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/write
    ", 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 file
    ", getpid());
    45     res = fcntl(file_desc, F_SETLK, &region_1);//对文件描述符,设置文件锁,在指向flock结构的指针region_1处
    46     if (res == -1) fprintf(stderr, "Failed to lock region 1
    ");//失败返回-1
    47     res = fcntl(file_desc, F_SETLK, &region_2);//对文件描述符,设置文件锁,在指向flock结构的指针region_2处
    48     if (res == -1) fprintf(stderr, "Failed to lock region 2
    ");    //失败返回-1
    49 
    50         /* and wait for a while */
    51     sleep(60);//等待一分钟
    52 
    53     printf("Process %d closing file
    ", 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 %d
    ", //首先打印一句话
    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 failed
    ");
    42             exit(EXIT_FAILURE);
    43         }//文件打开成功的话继续执行
    44         if (region_to_test.l_pid != -1) {//设定测试区域失败,也就是如果测试区域的记录带锁进程不是-1
    45             printf("Lock would fail. F_GETLK returned:
    ");
    46             show_lock_info(&region_to_test);//打印出获得的区域的锁描述
    47         }
    48         else {
    49             printf("F_WRLCK - Lock would succeed
    ");//成功的话就是设定独占锁成功
    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 %d
    ", 
    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 failed
    ");
    68             exit(EXIT_FAILURE);
    69         }
    70         if (region_to_test.l_pid != -1) {
    71             printf("Lock would fail. F_GETLK returned:
    ");
    72             show_lock_info(&region_to_test);            
    73         }
    74         else {//获取文件锁状态和设置区域锁都成功的话,执行打印
    75             printf("F_RDLCK - Lock would succeed
    ");
    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("	l_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 %d
    ", 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/write
    ", 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 %d
    ", 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 region
    ", getpid());//失败处理
     32     } else {
     33         printf("Process %d - obtained lock region
    ", 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 %d
    ", 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 region
    ", getpid());//失败处理
     45     } else {
     46         printf("Process %d - unlocked region
    ", 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 %d
    ", 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 region
    ", getpid());
     58     } else {
     59         printf("Process %d - unlocked region
    ", 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 %d
    ", 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 region
    ", getpid());
     71     } else {
     72         printf("Process %d - obtained lock on region
    ", 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 %d
    ", 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 region
    ", getpid());
     84     } else {
     85         printf("Process %d - obtained lock on region
    ", 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 %d
    ", 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 region
    ", getpid());
     97     } else {
     98         printf("Process %d - obtained lock on region
    ", getpid());
     99     }
    100 
    101     printf("Process %d ending
    ", 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秒


    万事走心 精益求美


  • 相关阅读:
    OSI安全体系结构
    PHP 二维数组根据相同的值进行合并
    Java实现 LeetCode 17 电话号码的字母组合
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 14 最长公共前缀
  • 原文地址:https://www.cnblogs.com/kongchung/p/4605169.html
Copyright © 2011-2022 走看看