shmop_open 的关键参数是什么?

mag*_*nes 3 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);
Run Code Online (Sandbox Code Playgroud)

(2)

   $shm_key = ftok(__FILE__, 't');
   $shm_id = shmop_open($shm_key, "c", 0644, 100);
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*ien 5

如果你去翻来源shmop_open(),你会看到该函数基本上是围绕POSIX的包装shmget()shmctl()shmat()程序。您可以看到$key参数 toshmop_open()作为 System V IPC 密钥传递给shmget()

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

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

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

请参阅如何为 Linux 中的进程间通信选择“密钥”?

Windows 上的 PHP 本身不支持共享内存功能。相反,它们通过“线程安全资源管理器”(TSRM) 进行模拟。您可以找到in的 TSRM 实现shmget()TSRM/tsrm_win32.c。众所周知,TSRM 共享内存模拟有些古怪(例如,请参阅此答案)。

对我来说似乎很奇怪的一件事是 TSRMshmget()实现通过以下方式构造了一个表示共享内存段的 Windows 文件映射名称:

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

因为“TSRM_SHM_SEGMENT:”的长度是 17 并且这个调用snprintf()最多将写入 24 个字符,所以只剩下 7 个字符作为键。因此,似乎只有介于 -999999 和 9999999 之间的键才应该与 Windows 上的 PHP 一起使用。