【发布时间】:2014-01-26 19:48:30
【问题描述】:
我正在尝试使用 shm_open 和 mmap 以及一个信号量在 MacOS X 上的两个进程之间共享一块内存。
我遇到的一个问题是,当我第二次运行程序时,当我尝试调用 shm_open() 时出现权限错误。
#include "SharedMemory.h"
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <cassert>
void * run_task(void * context);
const char * mem_name = "/tmp/my_mem2";
const char * sem_name = "/tmp/my_sem2";
int gFileDescr = -1;
void * gSharedMemoryAddr = NULL;
size_t gSharedMemorySize = 0;
sem_t * gSharedMemorySemaphore = NULL;
typedef struct {
completion_proc_t callback;
void * context;
} CallbackAndContext;
void setupSharedMem(size_t mem_size)
{
assert(-1 == gFileDescr);
assert(NULL == gSharedMemoryAddr);
assert(NULL == gSharedMemorySemaphore);
gSharedMemorySize = mem_size;
gFileDescr = shm_open(mem_name, O_RDWR | O_CREAT, 0);
if (gFileDescr <= 0) {
printf("Error, shm_open failed %d %s\n", errno, strerror(errno));
cleanup();
exit(-1);
}
if (ftruncate(gFileDescr, mem_size)) {
printf("ftruncate failed %d %s\n", errno, strerror(errno));
cleanup();
exit(-1);
}
gSharedMemoryAddr = mmap(0, mem_size, PROT_WRITE, MAP_SHARED, gFileDescr, 0);
if (gSharedMemoryAddr == (void *)-1) {
gSharedMemoryAddr = NULL;
printf("Could not map the memory: %d %s\n", errno, strerror(errno));
cleanup();
exit(-1);
}
// open a semaphore to sync memory access.
gSharedMemorySemaphore = sem_open(sem_name, O_CREAT, 0644, 1);
assert(gSharedMemorySemaphore);
int semval;
sem_getvalue(gSharedMemorySemaphore, &semval);
printf("The value of the semaphore is: %d\n", semval);
sem_wait(gSharedMemorySemaphore);
}
void cleanup()
{
if (gSharedMemorySemaphore)
sem_post(gSharedMemorySemaphore);
if (gSharedMemorySemaphore)
sem_close(gSharedMemorySemaphore);
if (gSharedMemoryAddr)
munmap(gSharedMemoryAddr, gSharedMemorySize);
shm_unlink(mem_name);
sem_unlink(sem_name);
}
void askForTask(unsigned char value, completion_proc_t completionProc, void * context)
{
unsigned char * memptr = (unsigned char *) gSharedMemoryAddr;
memptr[0] = value;
CallbackAndContext * candc = (CallbackAndContext *)malloc(sizeof(CallbackAndContext));
candc->callback = completionProc;
candc->context = context;
pthread_t myThread;
pthread_create(&myThread, NULL, run_task, (void *)candc);
}
void * run_task(void * context)
{
CallbackAndContext * candc = (CallbackAndContext *)context;
completion_proc_t comp_proc = NULL;
void * callback_context = NULL;
if (candc) {
comp_proc = candc->callback;
callback_context = candc->context;
free(candc);
}
printf("My Task runner started.\n");
// this will cause the task to start.
if (sem_post(gSharedMemorySemaphore)) {
printf("Error posting to semaphore: %d %s\n", errno, strerror(errno));
cleanup();
exit(-1);
}
// wait for task to be done.
if (sem_wait(gSharedMemorySemaphore)) {
printf("Error acquiring semaphore: %d %s\n", errno, strerror(errno));
cleanup();
exit(-1);
}
printf("Task over\n");
if (comp_proc) {
comp_proc(callback_context);
}
return NULL;
}
在我的 main.mm 文件中,它看起来像这样:
#define SHARED_MEMORY_BLOCK_SIZE 5000
unsigned char gValue = 0;
extern void * gSharedMemoryAddr;
NSConditionLock * taskLock;
enum {
waiting
,done
};
void MyCompletionProc(void * context)
{
assert(gSharedMemoryAddr);
unsigned char * valPtr = (unsigned char *)gSharedMemoryAddr;
printf("Task Complete Callback: %s\n", gValue == valPtr[1] ? "success" : "fail" );
[taskLock lock];
[taskLock unlockWithCondition:done];
}
int main(int argc, const char * argv[])
{
taskLock = [[NSConditionLock alloc] initWithCondition: waiting];
setupSharedMem(SHARED_MEMORY_BLOCK_SIZE);
NSDate * start_time = [NSDate date];
for (;[[NSDate date] timeIntervalSinceDate:start_time] < 30.0f;) {
askForTask(++gValue, MyCompletionProc, NULL);
[taskLock lockWhenCondition:done];
[taskLock unlockWithCondition:waiting];
sleep(1);
}
cleanup();
return 0;
}
(希望在其中混入 Objective-C 不会让人们感到困惑。)
我第一次运行该程序时,它似乎可以正常工作,大约每秒调用一次 askTask。 30 秒后,它会调用“清理”并退出。
在随后的运行中(除非我更改 mem_name/sem_name 的名称),我收到权限错误。当我重新启动计算机时它会消失,直到下一次。
我做错了什么,如何“重置”它或防止它进入这种状态?
跟进:似乎 shm_unlink 在 cleanup() 中失败,权限被拒绝。我不知道为什么。
【问题讨论】:
标签: macos semaphore shared-memory mmap