对于ftok的理解:
回顾了一下以前的实验,一直不理解为什么在消息队列做使用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
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。
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
shmget()分配一块共享内存
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
System V 的IPC对象有共享内存、消息队列、信号灯。
Msg_get
Shm_get
Sem_get
msgget(得到消息队列标识符或创建一个消息队列对象) |
msgctl (获取和设置消息队列的属性) |
msgsnd (将消息写入到消息队列) |
111111111111111111111111111111111111
shmget(得到一个共享内存标识符或创建一个共享内存对象)
shmdt(断开共享内存连接)
shmctl(共享内存管理)
222222222222222222222222222222222222222
semget(得到一个信号量集标识符或创建一个信号量集对象) |
系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。