来自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个字节。使用大数字键时,我能够处理更多内存。为什么呢?
答案 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一起使用。