我们知道,Windows中的共享内存是通过系统页面文件支持的内存映射文件实现的,并且始终以引用计数方式进行管理(http://msdn.microsoft.com/en-us/library/windows /desktop/aa366537(v=vs.85).aspx)。
我想知道Unix是否以类似的方式做到了。有人(http://stackoverflow.com/q/4278391/939142)说Unix也以引用计数方式管理shm。我在Mac OS X上尝试了一个实验,发现事实并非如此。
使用最后提供的代码,编译两个程序:host和client。型
./host
创建一个shm,在其第一个地址写入(int)10,然后退出。然后输入
./client <shmid>
检查shm段,它附加到创建的shm,打印第一个int,然后退出。
请注意,我们使用shmat和shmdt来连接/断开shm,并使用shmget来创建shm。
要销毁shm,我们必须使用shmctl手动完成。
结论: 在Unix中,shm不作为引用计数进行管理,至少对于Mac OS X
/************************** host.c ****************************/
#include <stdio.h>
#include <sys/shm.h>
#include <mach/vm_param.h>
#include <assert.h>
int
main(int argc, char** argv)
{
int value = 10;
int id;
void* ptr;
/* create a new shm */
id = shmget(IPC_PRIVATE, PAGE_SIZE, IPC_CREAT | 0666);
assert(id != -1);
/* attach to the new shm */
ptr = shmat(id, (const void*) NULL, 0);
assert((int*) ptr != -1);
/* print the id so that client can use */
printf("shm id = %ld\n", id);
printf("address of id = %ld, length = %ld\n", ptr, PAGE_SIZE);
((int*) ptr)[0] = value;
printf("value at address %ld = %ld\n", ptr, *(int*) ptr);
/* detach from the shm and exit */
shmdt((const void*) ptr);
return 0;
}
/************************** host.c ****************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include "assert.h"
#include <mach/vm_param.h>
int
main(int argc, char** argv)
{
void* ptr;
int id = atoi(argv[1]);
assert(id != -1);
/* attach to the shm */
ptr = shmat(id, NULL, 0);
assert(ptr != -1);
printf("value at ptr = %ld = %ld\n", ptr, *(int*) ptr);
shmdt((const void*) ptr);
return 0;
}
答案 0 :(得分:2)
它不是纯引用计数。根据shmctl(2):
IPC_RMID :标记要销毁的细分受众群。该细分受众群只会 实际上在最后一个进程分离后被销毁 (即,当相关结构的shm_nattch成员时 shmid_ds为零)。来电者必须是所有者或创作者,
这意味着:IPC_RMID
不会立即删除,但只有在下次引用计数降至零之后才会删除。
这允许您使用相同的工具实现多个目标:
服务器创建,附加并立即设置RMID
的服务器/客户端方法。然后只要服务器在这里,客户端就可以连接。如果服务器出现故障,客户端应断开连接,操作系统将清理资源。
或“消息”方法:有人写一条消息,将其固定到已知位置。之后,其他人可以来,寻找消息并采取相应行动。这就是你所做的。当然,这种方法对资源垃圾更加开放。但是有一些用例。