15

使用共享内存时,为什么要关心创建密钥

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,那么不只是每次都创建一个随机密钥有什么意义呢?

编辑

@Beej的 Unix IPC 指南可以阅读:

这种key胡说八道怎么办?我们如何创建一个?好吧,因为类型 key_t实际上只是 a long,所以你可以使用任何你想要的数字。但是,如果您对号码进行硬编码,而其他一些不相关的程序硬编码相同的号码但想要另一个队列怎么办?解决方案是使用ftok() 从两个参数生成密钥的函数。

读到这里,给我的印象是,需要附加到共享内存块上的是关键。但这不是真的,不是吗?

4

3 回答 3

16

整个 System V IPC 系统充满了这样的糟糕设计。(通过糟糕的设计,我的意思是共享资源的一个很小的命名空间,你必须依靠愚蠢的技巧ftok来获取密钥并祈祷它不会与使用的任何其他密钥发生冲突。)

如果可能的话,我会假装它不存在,并尽可能使用 POSIX 共享内存(同样使用 POSIX 线程同步原语代替 System V 信号量)。我能想到的唯一需要 System V 共享内存的实例是 X 共享内存映像扩展,也许还有其他 X 扩展。

编辑:为了更好地回答 OP 关于ftok:key_t通常是 32 位的目的的问题,是的,您可以自己选择一个 32 位的数字,但问题是人类不太可能选择所有数字,以及发生碰撞的可能性太高了。ftok允许您选择一个文件(对于您的应用程序来说是唯一的)和一个整数,并使用您选择的整数对文件的 inode 编号进行散列,这应该会导致键选择在键空间中的分布更加均匀。当然,您也可以只选择一个密钥,rand只要您有办法将结果传递给需要附加共享内存的其他进程。

于 2010-11-14T06:12:11.823 回答
14

是的,您需要使用 shmid 打开共享内存(使用shmat())来访问它shmget()。但是您将要访问的特定共享内存块是基于您正在使用的密钥,即希望通过 shm 进行通信的不同进程将需要使用相同的密钥。如果您只是使用随机数作为密钥,您可能会与其他一些不相关的程序发生冲突。

我打算建议看一下Beej 的 IPC 指南,但我看到你已经找到了 :)

于 2010-11-14T00:32:11.303 回答
1

shmid值仅在单个进程的上下文中有效,而key_t不同进程中的相同值将允许它们打开相同的共享内存段。

这就是为什么您需要key_t- 作为命名共享内存段的跨进程方式的原因。至于ftok(),正如其他答案所指出的那样,它用于降低两个不相关的进程组使用相同key_t值的概率。

于 2010-11-14T10:03:45.310 回答