在使用共享内存时,我们为什么要关心创build密钥
key_t ftok(const char *path, int id);
在下面的代码位?
key_t key; int shmid; key = ftok("/home/beej/somefile3", 'R'); shmid = shmget(key, 1024, 0644 | IPC_CREAT);
从我所了解的内容shmid
,访问一个给定的共享内存所需要的是shmid
,而不是key。 还是我错了? 如果我们需要的是shmid
,那么每次创build一个随机密钥都有什么意义呢?
@ Beej的Unix IPC指南可以读取:
这个
key
废话呢? 我们如何创build一个? 那么,因为typeskey_t
实际上只是一个long
,你可以使用任何你想要的数字。 但是如果你硬编码的数字和一些其他不相关的程序硬编码相同的数字,但希望另一个队列? 解决方法是使用ftok()
函数从两个参数生成一个键。
读这个,它给我的印象是,需要附加到共享内存块是关键。 但是这不是真的,是吗?
是的,在使用shmget()
打开共享内存之后,需要使用shmid访问共享内存(使用shmat()
shmget()
。 但是你要访问的特定的共享内存块是基于你正在使用的密钥,即不同进程希望通过shm进行通信将需要使用相同的密钥。 如果你只是使用一个随机数字作为一个键,你可能会碰到一些其他无关的程序。
我打算建议看看Beej的IPC指南,但是我发现你已经找到了:)
整个系统V IPC系统充满了这样的糟糕的设计。 (通过糟糕的设计,我的意思是一个共享资源的小命名空间,你必须依靠像愚蠢的窍门得到一个密钥,并祈祷它不会发生冲突与任何其他键使用。
如果可能的话,我会假装它不存在,并尽可能使用POSIX共享内存(同样,POSIX线程同步原语代替System V信号量)。 我能想到的唯一实例是你需要System V共享内存的地方是X共享内存映像扩展和其他X扩展。
编辑:为了更好地回答OP关于ftok
的目的的问题: key_t
通常是32位的,是的,你可以自己选择一个32位的数字,但问题是人类不可能选择所有的数字,的冲突是太高了。 ftok
允许你选择一个文件(打算是你的应用程序唯一的一个文件)和一个整数,并且用你选择的整数散列文件的inode号码,这将导致整个密钥空间的密钥选择分布更加均匀。 当然你也可以只用rand
来选择一个key,只要你有办法将结果传递给需要附加共享内存的其他进程。
shmid
值仅在单个进程的上下文中有效,而不同进程中相同的key_t
值将允许它们打开相同的共享内存段。
这就是为什么你需要一个key_t
作为命名一个共享内存段的跨进程方式。 至于ftok()
,正如其他答案所指出的那样,这是用来减少两个不相关的进程组使用相同的key_t
值的概率。