揭开消息队列相关函数ftok的真面目

消息队列、信号量、共享内存经常用在Linux服务端编程的进程间通信环境中,两个进程需要通过这三种方式去通信,那就需要约定好一个唯一的id号来进行通信,正好文件的设备编号和节点是唯一的,可对其稍加改造以产生一个唯一的编号,这时ftok()函数刚好具备这个条件可以去干这么一件事情

函数原型 意义
key_t ftok(const char *pathname, int id); 成功返回key_t键值,出错:-1,错误原因存于error中
参数 意义
pathname 文件名必须是存在的而且可以访问的,与权限无关
id 称为id子序号,只取低8位,1-255

到这里ftok基本就介绍完了,这里写个demo

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    struct stat stat1;
	if ( argc != 2 )
    {
		printf("usage: ftok < pathname >" );
		exit(1);
    }
    stat( argv[1], &stat1 ) ;
    printf("st_dev:%lx, st_ino:%lx, key:%x\n",
		(unsigned long)stat1.st_dev, (unsigned long)stat1.st_ino, ftok(argv[1],0x01 ));
    printf("st_dev:%lx, st_ino:%lx, key:%x\n",
		(unsigned long)stat1.st_dev, (unsigned long)stat1.st_ino, ftok(argv[1],0x002 ));
	exit(0);
}

以上demo的执行结果如下:

root@mcchen:/home/ftok# ls -i ftok
1846264 ftok
root@mcchen:/home/ftok# ./ftok ftok
st_dev:fc01, st_ino:1c2bf8, key:1012bf8
st_dev:fc01, st_ino:1c2bf8, key:2012bf8

通过执行结果可看出,ftok获取的键值是由ftok()函数的第二个参数的后8个bit,st_dev的后两位,st_ino的后四位构成的
这里就有一个疑问,如果把pathname删除掉然后再重新创建会怎样,返回的key和删除前的都一样吗?答案是否定的,也就是不一定
第一种情况:在arm 32位机器上执行结果截的图,inode改变了
在这里插入图片描述
第二种情况:在ubuntu64位机器上执行结果,inode没变

root@mcchen:/home/ftok# ls -i msg1.q 
1846265 msg1.q
root@mcchen:/home/ftok# rm msg1.q 
root@mcchen:/home/ftok# touch msg1.q
root@mcchen:/home/ftok# ls -i msg1.q 
1846265 msg1.q 

所以要确保key值不变,要么确保ftok()的文件不被删除,要么不用ftok(),指定一个固定的key值,至于以上的两种情况为什么查出来的inode一种会变化,一种不会变化,目前还不太清楚,如果读到这里的朋友们有知道的,欢迎评论区留言,多谢!

发布了45 篇原创文章 · 获赞 38 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/muchong123/article/details/105209295