【转载】ftok函数解析

原文链接

ftok函数用途

由于共享内存,消息队列,信号量都是通过中间介质进行通信的,这种介质非常多,想要通过唯一一个介质进行通信,就需要像身份证号来区分人一样去区分这些介质呢?使其具有唯一性。正好文件的设备编号和节点是唯一的,可对其稍加改造以产生一个唯一的编号,ftok()函数就是去做这件事的。ftok函数具体形式如下:

    key_t ftok(const char *pathname, int id);

其中参数pathname是指定的文件名,这个文件必须是存在的而且可以访问的。id是子序号,它是一个8bit的整数。即范围是0~255。当函数执行成功,则会返回key_t键值,否则返回-1。在一般的UNIX中,通常是将文件的索引节点取出,然后在前面加上子序号就得到key_t的值。

关于ftok函数的一些疑问

  • pathname是目录还是文件的具体路径?是否可以随便设置呢?ftok根据路径名,提取文件信息,再根据这些文件信息及id合成key,该路径可以随便设置。
  • pathname指定的目录或文件的权限是否有要求?该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
  • id是否可以随便设定,有什么限制条件吗?id是可以根据自己的约定,随意设置。在UNIX系统上,它的取值是1到255。

ftok函数的使用陷阱

使用ftok()函数时,里面有两个参数,即pathname和id,pathname为指定的文件名,而id为子序列号,这个函数的返回值就是key,它与指定的文件的索引节点号和子序列号id有关,这样就会给我们一个误解,即只要文件的路径,名称和子序列号不变,那么得到的key值永远就不会变。
事实上,这种认识是错误的,想想一下,假如存在这样一种情况:在访问同一共享内存的多个进程先后调用ftok()时间段中,如果pathname指向的文件或者目录被删除而且又重新创建,那么文件系统会赋予这个同名文件新的i节点信息,于是这些进程调用的ftok()都能正常返回,但键值key却不一定相同了。由此可能造成的后果是,原本这些进程意图访问一个相同的共享内存对象,然而由于它们各自得到的键值不同,实际上进程指向的共享内存不再一致;如果这些共享内存都得到创建,则在整个应用运行的过程中表面上不会报出任何错误,然而通过一个共享内存对象进行数据传输的目 的将无法实现。
所以要确保key值不变,要么确保ftok()的文件不被删除,要么不用ftok(),指定一个固定的key值。

ftok函数工作原理

#include <stdio.h>       
#include <stdlib.h>  
#include <sys/stat.h>

int main()
{
char filename[50];
struct stat buf;
int ret;
strcpy( filename, "/home/satellite/" );
ret = stat( filename, &buf );
if( ret )
{
printf( "stat error\n" );
return -1;
}

    <span class="token function">printf</span><span class="token punctuation">(</span> <span class="token string">"the file info: ftok( filename, 0x27 ) = %x, st_ino = %x, st_dev= %x\n"</span><span class="token punctuation">,</span> <span class="token function">ftok</span><span class="token punctuation">(</span> filename<span class="token punctuation">,</span> <span class="token number">0x27</span> <span class="token punctuation">)</span><span class="token punctuation">,</span> buf<span class="token punctuation">.</span>st_ino<span class="token punctuation">,</span> buf<span class="token punctuation">.</span>st_dev <span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

以上程序输出

the file info: ftok( filename, 0x27 ) = 2704e2ee, st_ino = 74e2ee, st_dev= 1000004

通过执行结果可看出,ftok获取的键值是由ftok()函数的第二个参数的后8个bit,st_dev的后两位,st_ino的后四位构成的。

//函数:int stat( const char *file_name, struct stat *buf )
//函数说明:通过文件名filename,获取文件信息,并保存在buf所指的结构体stat中。
//返回值:成功执行返回0,失败返回-1,错误代码存于errno
//struct stat结构体的定义如下:
struct stat {
       unsigned long  st_dev;//文件的设备编号
       unsigned long  st_ino;//节点
       unsigned short st_mode; //文件的类型和存取的权限
       unsigned short st_nlink;//连到该文件的硬连接数目,刚建立的文件值为1
       unsigned short st_uid; //用户ID
       unsigned short st_gid; //组ID
       unsigned long st_rdev; 
       unsigned long  st_size;
       unsigned long st_blksize;
       unsigned long  st_blocks;
       unsigned long  st_atime;
       unsigned long st_atime_nsec;
       unsigned long  st_mtime;
       unsigned long st_mtime_nsec;
       unsigned long  st_ctime;
       unsigned long st_ctime_nsec;
       unsigned long  __unused4;
       unsigned long  __unused5;
};

posted on 2020-04-27 11:08  Peiah  阅读(1072)  评论(1)    收藏  举报