shmop_open关键参数是什么?

时间:2015-10-18 12:31:22

标签: php windows shared-memory

来自PHP,它说

  

int shmop_open(int $ key,string $ flags,int $ mode,int $ size)

其中$ key是

  

共享内存块的系统ID。可以作为十进制或十六进制传递。

有些人用任意数字(1)填充$ key,而其他人使用文件获取$ key值(2)。 $ key是随机值吗?。

(1)

   $shm_id = shmop_open(987654, "c", 0644, 100);

(2)

   $shm_key = ftok(__FILE__, 't');
   $shm_id = shmop_open($shm_key, "c", 0644, 100);

顺便说一句,在Windows中,我使用了一个小数字,虽然它有效,但我最多只能使用1024个字节。使用大数字键时,我能够处理更多内存。为什么呢?

1 个答案:

答案 0 :(得分:3)

如果查看source of shmop_open(),您会看到该函数基本上是POSIX shmget()shmctl()shmat()例程的包装器。您可以看到$key shmop_open()参数作为System V IPC密钥传递给shmget()

shmget()返回与给定密钥关联的共享内存段的标识符。如果传递给shmget()的密钥是特殊值IPC_PRIVATE,那么这指的是一个唯一的共享内存段,只能由fork()创建的后代进程继承(注意这可能是与您的案件无关)。否则,为了让两个进程访问同一个共享内存段,他们需要使用相同的密钥获取该段的标识符。

您可以使用固定密钥,就像您引用的第一个示例一样。但是,使用固定键很容易发生意外碰撞。

更好的方法是使用ftok()。如果您始终使用ftok()生成密钥,那么由于ftok()保证生成的密钥在使用不同的id值或使用的路径调用时会有所不同,因此冲突的风险会降低在同一文件系统上同时命名两个不同的文件。

请参阅How to choose the "Key" for inter-processes communication in Linux?

Windows上的PHP本身不支持共享内存功能。相反,它们是通过“线程安全资源管理器”(TSRM)模拟的。您可以在TSRM/tsrm_win32.c中找到the TSRM implementation of shmget()。众所周知,TSRM共享内存仿真有点古怪(例如见this answer)。

对我来说似乎有些奇怪的是,TSRM shmget()实现通过以下方式构造表示共享内存段的Windows文件映射名称:

char shm_segment[26], shm_info[29];
/* ... */
snprintf(shm_segment, sizeof(shm_segment)-1, "TSRM_SHM_SEGMENT:%d", key);

因为“TSRM_SHM_SEGMENT:”的长度为17,并且对snprintf()的调用最多可写入24个字符,因此该密钥只留下7个字符。因此,似乎只有-999999和9999999之间的密钥才能在Windows上与PHP一起使用。