SystemV中ftok()应该注意的问题

    今天看到同事写的代码,在多进程之间做互斥时,使用semget()获取信号量的值。其中的变量key通过ftok()获得。

    以上的操作都是符合逻辑的,也没有问题。

    但是他怕信号量文件被删掉,在ftok()之前,查看了该文件是否存在,并且当文件不存在时,创建文件。

    一切看上去都是那么合理。但是ftok()这么使用存在很大的风险。即便是同样的文件名称、路径,也可能会生成的不同key_t类型变量。其实之前我也不是很确定,只是感觉ftok()不会这么傻的像同事认为的那样,只靠一个字符串(路径名)来获取key,仔细看了看手册,里面有如下的描述:


 

       The  resulting  value  is the same for all pathnames that name the same file, when the same value of proj_id is used. The

       value returned should be different when the (simultaneously existing) files or the project IDs differ.

 


    注意括号中的simultaneously,我英语不好,之前一直忽略了这个词,刚才查了下,这里指明了文件必须是同时生成的。我的假设在手册里得到了证明。不妨再写个小程序测试一下:


/********** main.c, begin **********/

 

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>



int main()

{

        key_t val = 0;

        int pro_j = 's';

        char path[256] = "/tmp/hello.ftok";

        val = ftok(path, pro_j);

        printf("ftok() return %u/n", val);

        return 0;

}


/********** main.c, end **********/

 


    编译,运行:

~# gcc -g -Wall main.c -o main

~# touch /tmp/hello.ftok

~# ./main

ftok() return 1929382828

    此时根据/tmp/hello.ftok生成了一个key。删除文件,但不马上创建文件,先创建两个无关的文件,让它们占用之前的目录树中的节点---文件的大小是相同的,时间会不同,但是时间应该不是关键因素,尝试下其他的方式。

~# rm -f /tmp/hello.ftok

~# touch /tmp/test1.ftok

~# touch /tmp/test2.ftok

~# touch /tmp/hello.ftok

    再次调用main,查看结果:

~# ./main

ftok() return 1929382830

    哈哈哈哈哈,值真的变了!并且增加了2。查看源码,看看到底是什么左右了ftok()的返回值:


/********** glibc-2.7, sysvipc/ftok.c, begin **********/

 

#include <sys/ipc.h>

#include <sys/stat.h>


key_t

ftok (pathname, proj_id)

     const char *pathname;

     int proj_id;

{

  struct stat64 st;

  key_t key;


  if (__xstat64 (_STAT_VER, pathname, &st) < 0)

    return (key_t) - 1;


  key = ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16)

| ((proj_id & 0xff) << 24));


  return key;

}

 


/********** glibc-2.7, sysvipc/ftok.c, end **********/


    函数的源码很简单(这个文件也很简单,总共才38行!),通过__xstat64获取了文件的属性,可以看到,当proj_id不变时,key的值与文件属性中的节点号和文件所属的设备号有关!

    或许当你在做简单测试的时候,删掉文件,再创建一个文件,发现生成的key没有变化,但是当程序部署在大型的系统中时,很有可能因为文件的节点号不同,获取到不同的key,导致对数据的保护失败,而这种bug,在写完代码之后,很难发现。

    所以我建议,不要在程序中生成ftok()中所指定的文件,而是通过工程人员手工添加此文件。如果发现文件不存在时,程序大可退出,当用户使用的方便性和程序运行的安全相冲突时,还是考虑先程序和数据的安全吧。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值