对于ftok的理解

  • Post author:
  • Post category:其他


回顾了一下以前的实验,一直不理解为什么在消息队列中要使用ftok,比如下面的一个实例

if((key=ftok(".",'a'))==-1){
     perror("ftok");
    exit(1);  }
    qid=msgget( key, IPC_CREAT | 0666 );       /*创建一个消息队列*/
    if ( qid < 0 ) {   /* 创建一个消息队列失败 */
        perror ( "msgget" );
        exit (1) ;
    }
  printf ("created queue id : %d \n", qid );  /* 输出消息队列的ID */

要先生成一个key,再调用msgget()得到消息队列的id。

搜了百度百科的一段贴在下面先建立起对ftok基本的了解:

key_t ftok( const char * fname, int id )

fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:

key_t key;

key = ftok(“.”, 1); 这样就是将fname设为当前目录。

id是子序号。

在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。

如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。

为什么要使用ftok()函数(可以如此记忆:file to key)把一个已存在的路径名和一个整数标识符转换成一个key_t值?我的理解就是:现在假如有两个应用程序处于同一目录下,并且这两个应用程序要通过一个消息队列进行通信,现在第一个应用程序开起来,通过msgget()得到了一个消息队列id,而第二个应用程序怎么知道是使用这个消息队列id进行通信呢?

第一种方法如下所示:

./send  ,让这个进程输出它所创建的消息队列id,比如输出11111. 再./receive 11111,运行第二个程序,11111当成参数传入。在receive这个程序里面要将argv[1]当成消息队列的id,这种方法缺点很明显,每次都要手动输入。

第二种方法就是ftok了,利用ftok得到一个键值,这个键值只和inode有关,并且在第二应用程序里面也写上实例中的代码,则两个应用程序能得到相同的键值,之后通过这个键值能得到内核中的消息队列的id,而msgget()的参数单独使用IPC_CREAT时,要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。所以第一个程序调用msgget()会根据这个键值创建出消息队列id,而第二个程序使用相同的键值调用msgget()能得到这个键值对应的消息队列的id,这样就不用向方法一那样手动输入了。

总结下就是消息队列id是一个进程的内部名,自己创建的一个消息队列id其他进程怎么会知道呢!所以为使得多个合作进程能够在同一个消息队列对象上会合,需要一个外部名方案,那就是使用了键(key),对于相同的路径每个进程能得到相同的键值,内核再根据这个键值能得到消息队列id。



版权声明:本文为heiworld原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。