【发布时间】:2014-04-11 07:19:16
【问题描述】:
我在共享内存方面遇到问题。我有一个进程可以很好地创建和写入共享内存段。但是我无法获得第二个过程来附加相同的现有段。如果我使用 IPC_CREATE 标志,我的第二个进程可以创建一个新的共享段,但我需要附加到由第一个进程创建的现有共享段。
这是我在第二个过程中的代码:
int nSharedMemoryID = 10;
key_t tKey = ftok("/dev/null", nSharedMemoryID);
if (tKey == -1) {
std::cerr << "ERROR: ftok(id: " << nSharedMemoryID << ") failed, " << strerror(errno) << std::endl;
exit(3);
}
std::cout << "ftok() successful " << std::endl;
size_t nSharedMemorySize = 10000;
int id = shmget(tKey, nSharedMemorySize, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (id == -1) {
std::cerr << "ERROR: shmget() failed, " << strerror(errno) << std::endl << std::endl;
exit(4);
}
std::cout << "shmget() successful, id: " << id << std::endl;
unsigned char *pBaseSM = (unsigned char *)shmat(id, (const void *)NULL, SHM_RDONLY);
if (pBaseSM == (unsigned char *)-1) {
std::cerr << "ERROR: shmat() failed, " << strerror(errno) << std::endl << std::endl;
exit(5);
}
std::cout << "shmat() successful " << std::endl;
问题是第二个进程在调用 shmget() 时总是出错,并出现“没有这样的文件或目录”错误。但这是我在第一个过程中使用的完全相同的代码,它在那里工作得很好。在创建共享段的第一个进程中,我可以写入内存段,我可以使用“ipcs -m”查看它另外,如果我从段的“ipcs -m”命令中获取 shmid 并对其进行硬编码在我的第二个过程中,第二个过程可以很好地附加到它上面。所以问题似乎是两个进程用来识别单个共享段的公共 id 的生成。
我有几个问题:
(1) 有没有更简单的方法来获取现有共享内存段的 shmid?对我来说,我必须将 三个 单独的参数从第一个进程(创建段)传递给第二个进程,这样第二个进程才能获得相同的共享段,这对我来说似乎很疯狂。我可以忍受必须传递 2 个参数:像“/dev/null”这样的文件名和相同的共享 ID(我的代码中的 nSharedMemoryID)。但是为了获得 shmid 而必须传递给 shmget() 例程的段的大小似乎毫无意义,因为我不知道实际分配了多少内存(由于页面大小问题)所以我不能肯定是一样的。 (2) 我在第二个进程中使用的段大小是否必须与最初在第一个进程中创建段的段的大小相同?我试图将其指定为 0,但仍然出现错误。 (3) 同样,权限是否必须相同?也就是说,如果共享段是用用户/组/世界的读/写创建的,第二个进程可以只为用户使用读吗? (两个进程的相同用户)。 (4) 当两个进程都明显存在文件“/dev/null”时,为什么 shmget() 会失败并出现“没有这样的文件或目录”错误?我假设第一个进程没有在该节点上设置某种锁,因为那是没有意义的。
感谢任何人提供的任何帮助。我已经为此苦苦挣扎了好几个小时——这意味着我可能正在做一些非常愚蠢的事情,当有人指出我的错误时,我最终会让自己感到尴尬:-)
谢谢, -安德烈斯
【问题讨论】:
-
当附加(现有)段的进程调用
shmget时,它应该将大小指定为0。这样就消除了您的抱怨之一。页面大小等,不包括在内。这应该与这些目的无关。权限类似于文件权限。仅仅因为您为用户创建了一个带有 r/w 的文件并不意味着用户必须在每个 pgm 中以 r/w 的形式打开它。您可以选择以只读或只写方式打开它。权限是给你,嗯,权限,而不是提出要求。 -
感谢您的回复鸭子。在第二个进程 shmget() 中使用 0 作为大小对我来说是有意义的——感谢您确认,所以我知道这不是问题。
-
由于这似乎围绕
ftok展开,您是否查看过在调试器或 printf 中返回的 key_t?我认为它只是 typedef 后面的一个 int。 -
不是调试器,但我已经打印出创建共享段的第一个进程和尝试附加到它的第二个进程的密钥,它们确实是完全相同的密钥--即使在多次运行的程序中,它们都是一样的,这是有道理的。
标签: c++ linux posix ipc shared-memory