ftok API
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
- ftok根据路径名,提取文件信息,再根据这些文件信息及project ID合成key,该路径可以随便设置。
- 该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
- proj_id是可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;
pathname 相对路径和绝对路径都可以
ftok()函数的一个陷阱
在访问同一共享内存的多个进程先后调用ftok()时间段中,如果fname指向的文件或者目录被删除而且又重新创建,那么文件系统会赋予这个同名文件新的i节点信息,于是这些进程调用的ftok()都能正常返回,但键值key却不一定相同了。由此可能造成的后果是,原本这些进程意图访问一个相同的共享内存对象,然而由于它们各自得到的键值不同,实际上进程指向的共享内存不再一致;如果这些共享内存都得到创建,则在整个应用运行的过程中表面上不会报出任何错误,然而通过一个共享内存对象进行数据传输的目 的将无法实现。
所以要确保key值不变,要么确保ftok()的文件不被删除,要么不用ftok(),指定一个固定的key值。
ftok()产生键值的原理
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
int main(int argc,char *argv[])
{
if(argc < 3){
printf("useage%s filename proj_id[1-255]\n",argv[0]);
exit(0);
}
int proj_id = atoi(argv[2]);
key_t key = ftok(argv[1],proj_id);
printf("proj_id(10) : %d proj_id(16):%x\n",proj_id,proj_id);
if(key == -1){
fprintf(stderr,"error: %s\n",strerror(errno));
exit(1);
}
struct stat buf;
int ret;
ret = stat(argv[1],&buf);
if(ret){
perror("stat error");
exit(1);
}
printf("the file info:ftok id:%x, st_ino =%x, st_dev = %x\n",key,buf.st_ino,buf.st_dev);
return 0;
}
}
结果:
ftok获取的键值是由ftok()函数的第二个参数的后8个bit,st_dev(文件的设备编号)的后两位,st_ino(文件节点)的后四位构成的
有关 st_dev和 st_ino的定义如下:
函数:int stat( const char *file_name, struct stat *buf )
函数说明:通过文件名filename,获取文件信息,并保存在buf所指的结构体stat中。
返回值:成功执行返回0,失败返回-1,错误代码存于errno
struct stat结构体的定义如下:
/usr/include/asm/stat.h
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;
};