免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2915 | 回复: 3
打印 上一主题 下一主题

文件读写锁的小问题,求指导 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-25 10:30 |只看该作者 |倒序浏览
我在看Beginning linux programming第三版。在第七章的时候看到自己机子上的跟书上的讲的不一样。简单描述一下:在文件的某个部分加上读锁的话可以再其上再加读锁,但不能加写锁;在某个部分加上写锁之后读锁和写锁都不能再加。但是在我的linux上(Fedora)上,我按照书上讲的加了一个写锁,但是再其上仍然可以加读锁。代码如下:file_lock3的代码:
C/C++ code
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

int main()
{
    //some variable
    int file_desc;
    const char *test_file = "/tmp/test_lock";
    int byte_count;
    char *byte_to_write = "A";
    struct flock region_1;
    struct flock region_2;
    int res;

    //open a file
    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);
    }   
   
    // write somen data
    for(byte_count = 0; byte_count < 100; byte_count++)
    {   
        write(file_desc, byte_to_write, 1);
    }   
   
    // add the share lock to the 10-30 byte region
    region_1.l_type = F_RDLCK;
    region_1.l_whence = SEEK_SET;
    region_1.l_start = 10;
    region_1.l_len = 20;

    // add the write lock to the 40-50 byte region
    region_2.l_type = F_WRLCK;
    region_2.l_whence = SEEK_SET;
    region_2.l_start = 40;
    region_2.l_len = 10;

    // lock the file
    printf("Process %d locking file\n", getpid());
    res = fcntl(file_desc, F_SETLK, &region_1);
    if(res == -1)
    {
        fprintf(stderr, "Failed to lock the region 1\n");
    }
    res = fcntl(file_desc, F_SETLK, &region_2);
    if(res == -1)
    {
        fprintf(stderr, "Failed to lock region 2\n");
    }

    // wait 60 seconds
    sleep(60);

    printf("Process %d release the lock\n", getpid());
    close(file_desc);
    exit(EXIT_SUCCESS);
}


file_lock4的代码:
C/C++ code

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#define SIZE_TO_TRY 5

void show_lock_info(struct flock *);

int main()
{
    int file_desc;
    const char *test_file = "/tmp/test_lock";
    int res;
    struct flock region_to_test;
    int start_byte;

    //open the test_file
    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);
    }   

    //test region by SIZE_TO_TRY byte
    for(start_byte = 0; start_byte < 99; start_byte += SIZE_TO_TRY)
    {   
        //test use the write lock
        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_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("Test F_RDLCK on region from %d to %d\n", start_byte, start_byte+SIZE_TO_TRY);

        res = fcntl(file_desc, F_GETLK, &region_to_test);
        if(res == -1)
        {
            fprintf(stderr, "F_GETLK Failed\n");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("F_RDLCK - Lock would succeed\n");
        }
    }
    close(file_desc);
    exit(EXIT_SUCCESS);
}
void show_lock_info(struct flock *to_show)
{
    printf("l_type %d, ", to_show->l_type);
    printf("l_whence %d, ", to_show->l_whence);
    printf("l_start %d, ", to_show->l_start);
    printf("l_len %d, ", to_show->l_len);
    printf("l_pid %d, ", to_show->l_pid);
}


然后我用这样的命令运行 ./file_lock3 & ; ./file_lock4
运行的结果和书上不一样
Testing F_WRLCK on region from 0 to 5
F_WRLCK - Lock would succeed
Test 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
Test 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 2289, Test 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 2289, Test 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 2289, Test 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 2289, Test 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
Test 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
Test 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 2289, Test F_RDLCK on region from 40 to 45
F_RDLCK - Lock would succeed
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 2289, Test F_RDLCK on region from 45 to 50
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 50 to 55
F_WRLCK - Lock would succeed
Test 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
Test 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
Test 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
Test 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
Test 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
Test 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
Test 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
Test 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
Test 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
Test F_RDLCK on region from 95 to 100
F_RDLCK - Lock would succeed


最好是看过这本书的做过这个实验的帮我解答一下,谢谢

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
2 [报告]
发表于 2011-05-25 11:14 |只看该作者
本帖最后由 cokeboL 于 2011-05-25 11:17 编辑

回复 1# wsw908


没看过这书,这个不是书上代码吧。

第一个程序在不同区域分别加了读、写锁,没啥问题。

第二个程序你用的是F_GETLK:
  1. • F_GETLK 决定由f l o c k p t r所描述的锁是否被另外一把锁所排斥(阻塞)。如果存在一把
  2. 锁,它阻止创建由f l o c k p t r所描述的锁,则这把现存的锁的信息写到f l o c k p t r指向的结构中。如
  3. 果不存在这种情况,则除了将l t y p e设置为F U N L C K之外,f l o c k p t r所指向结构中的其他信息
  4. 保持不变。——摘自APUE高级I/O记录锁部分
复制代码
而对于fcntl的返回值,只有出错的时候返回-1,出错情况包括被信号中断之类的,但F_GETLK这种参数,
不管是按flockptr设置了还是被拒绝设置返回了,都应该算是执行成功,所以都不是返回-1,if else判断条件
就用得不恰当了(这块我没具体试验,楼主打印下返回值看看然后把结果说下哈)。

另外这段代码:
  1.        region_to_test.l_type = F_WRLCK;
  2.         region_to_test.l_whence = SEEK_SET;
  3.         region_to_test.l_start = start_byte;
  4.         region_to_test.l_len = SIZE_TO_TRY;
  5.         region_to_test.l_type = F_RDLCK;
  6.         region_to_test.l_whence = SEEK_SET;
  7.         region_to_test.l_start = start_byte;
  8.         region_to_test.l_len = SIZE_TO_TRY;
  9.         region_to_test.l_pid = -1;
复制代码
自己赋值马上又改了没必要,一次就行了,如果读、写都想试那就赋一次F_GETLK一次。

不知道对不对~

论坛徽章:
0
3 [报告]
发表于 2011-05-25 16:26 |只看该作者
非常感谢楼上的回答。

第一、是书上的源代码没有错,不过是我不小心写代码的时候抄错了。
第二、第二个自己赋值确实没必要改那么多,只需要改一个l_type和l_pid就可以了,照书上抄的,偷懒没有多思考,该打。

听了你的提示我后面自己查看了我自己的代码,终于找到失误的地方了,就是判断条件不对。真的是,写代码不懂脑子,灰常感谢楼上的回答。
  1. if(res == -1)
  2.         {
  3.             fprintf(stderr, "F_GETLK Failed\n");
  4.             exit(EXIT_FAILURE);
  5.         }
  6.         else
  7.         {
  8.             printf("F_RDLCK - Lock would succeed\n");
  9.         }
复制代码
应该为
  1. if(res == -1)
  2.         {
  3.             fprintf(stderr, "F_GETLK Failed\n");
  4.             exit(EXIT_FAILURE);
  5.         }
  6.         if(region_to_test.l_pid != -1)
  7.         {
  8.             printf("Lock would fail. F_GETLK returned :\n");
  9.             show_lock_info(&region_to_test);
  10.         }
  11.         else
  12.         {
  13.             printf("F_RDLCK - Lock would succeed\n");
  14.         }
复制代码

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
4 [报告]
发表于 2011-05-25 16:36 |只看该作者
回复 3# wsw908


不客气~
APUE还是蛮好的~linux编程接口蛮好的~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP