如何附加到现有的共享内存段 [英] how to attach to an existing shared memory segment

查看:218
本文介绍了如何附加到现有的共享内存段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在共享内存中遇到问题。我有一个进程创建和写入共享内存段就好了。但我不能得到第二个过程来附加同一现有段。如果我使用IPC_CREATE标志,但我需要附加到第一个进程创建的现有共享段,我的第二个进程可以创建一个新的共享段。

I am having trouble with shared memory. I have one process that creates and writes to a shared memory segment just fine. But I cannot get a second process to attach that same existing segment. My second process can create a new shared segment if I use IPC_CREATE flag but I need to attach to the existing shared segment that was created by the 1st process.

这是我的第二个进程中的代码:

This is my code in the 2nd process:

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;



<这样的文件或目录错误。但是这是我在第一个过程中使用的完全相同的代码,它的工作就好了。在创建共享段的第一个进程,我可以写入内存段,我可以看到它与ipcs -m另外,如果我从段的ipcs -m命令获得shmid并硬编码在我的第二个过程和第二个过程可以附加到它只是罚款。因此,问题似乎是两个进程用来识别单个共享段的通用id的生成。

The problem is that the 2nd process always errors out on the call to shmget() with a "No such file or directory" error. But this is the exact same code I used in the 1st process and it works just fine there. In the 1st process that created the shared segment, I can write to the memory segment, I can see it with "ipcs -m" Also, if I get the shmid from the "ipcs -m" command of the segment and hard code it in my 2nd process and the 2nd process can attach to it just fine. So the problem seems to be generation of the common id that both processes use to identify a single shared segment.

我有几个问题:

(1)有更简单的方法来获取现有共享内存段的shmid吗?对我来说似乎很疯狂,我必须从第一个进程(创建段)的第三个进程传递三个单独的参数到第二个进程,所以第二个进程可以获得相同的共享段。我可以忍受不得不传递2个参数:文件名像/ dev / null和相同的共享id(我的代码中的nSharedMemoryID)。但是为了获得shmid而必须传递给shmget()例程的段的大小似乎毫无意义,因为我不知道实际分配了多少内存(因为页面大小问题),所以我不能肯定是一样的。
(2)我在第二个进程中使用的段大小必须与在第一个进程中用于最初创建段的段的大小相同吗?我试图指定为0,但我仍然得到错误。
(3)同样,做权限必须一样吗?也就是说,如果共享段是创建用户/组/世界的读/写,第二个进程只是使用读为用户? (两个进程的相同用户)。
(4)和为什么当两个进程显然都存在文件/ dev / null时,shmget()失败并显示No such file or directory错误?我假设第一个进程没有在这个节点上放一些锁,因为这是没有意义的。

(1) Is there an easier way to get the shmid of an existing shared memory segment? It seems crazy to me that I have to pass three separate parameters from the 1st process (that created the segment) to the 2nd process just so the 2nd process can get the same shared segment. I can live with having to pass 2 parameters: the file name like "/dev/null" and the same shared id (nSharedMemoryID in my code). But the size of the segment that has to be passed to the shmget() routine in order to get the shmid seems senseless because I have no idea of exactly how much memory was actually allocated (because of the page size issues) so I cannot be certain it is the same. (2) does the segment size that I use in the 2nd process have to be the same as the size of the segment used to initially create the segment in the 1st process? I have tried to specify it as 0 but I still get errors. (3) likewise, do the permissions have to be the same? that is, if the shared segment was created with read/write for user/group/world, can the 2nd process just use read for user? (same user for both processes). (4) and why does shmget() fail with the "No such file or directory" error when the file "/dev/null" obviously exists for both processes? I am assuming that the 1st process does not put some kind of a lock on that node because that would be senseless.

感谢任何人可以给任何帮助。我一直在努力工作了几个小时 - 这意味着我可能在做一些真的愚蠢的事情,最终会让人感到尴尬,当有人指出我的错误: - )

Thanks for any help anyone can give. I have been struggling with this for hours--which means I am probably doing something really stupid and will ultimately embarrass myself when someone points out my error :-)

谢谢,
-Andres

thanks, -Andres

推荐答案

(1):附加过程扫描用户的现有段,尝试附加所需的大小,在段的开头检查魔术字节序列(以排除同一用户的其他程序)。或者,您可以检查附加的进程是否是您期望的进程。如果其中一个步骤失败,这是第一个,将创建段...笨重是,我看到它在一个代码从70年代。

(1) as a different way: the attaching process scan the existing segments of the user, tries to attach with the needed size, check for a "magic byte sequence" at the beginning of the segment (to exclude other programs of the same user). Alternatively you can check if the process attached is the one that you expect. If one of the steps fails, this is the first one and will create the segment... cumbersome yes, I saw it in a code from the '70s.

最后,您可以评估使用符合POSIX的 shm_open()替代 - 应该更简单或至少更现代...

Eventually you can evaluate to use the POSIX compliant shm_open() alternative - should be simpler or at least more modern...

(2)关于大小,重要的是指定的大小小于/等于现有细分的大小,因此如果四舍五入到下一个内存页大小。

(2) Regarding the size, it's important that the size specified be less/equal than the size of the existing segment, so no issues if it's rounded to the next memory page size. you get the EINVAL error only if it's larger.

(3)模式标志仅在第一次创建段时才相关(绝对可靠)。

(3) the mode flags are only relevant when you create the segment the first time (mostly sure).

(4) shmget()失败并且没有这样的文件或目录它没有找到具有(现在是pedantic:不是 id - id)的段,我们通常引用 shmget ),后来使用) - 你检查过 tKey 是否相同?您的代码在我的系统上正常工作。只是添加了一个main()。

(4) The fact that shmget() fail with the "No such file or directory" means only that it hasn't found a segment with that key (being now pedantic: not id - with id we usually refer to the value returnet by shmget(), used subsequently) - have you checked that the tKey is the same? Your code works fine on my system. Just added a main() around it.

编辑:附加工作程序

#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char **argv) {

  int nSharedMemoryID = 10;
  if (argc > 1) {
    nSharedMemoryID = atoi(argv[1]);
  }

  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. key = " << tKey << std::endl;

  size_t nSharedMemorySize = 10000;
  int id = shmget(tKey, nSharedMemorySize, 0);
  if (id == -1)  {
    std::cerr << "ERROR: shmget() failed (WILL TRY TO CREATE IT NEW), " << strerror(errno) << std::endl << std::endl;
    id = shmget(tKey, nSharedMemorySize, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | IPC_CREAT);
    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;
}

EDIT:output

output

$ ./a.out 33
ftok() successful. key = 553976853
ERROR: shmget() failed (WILL TRY TO CREATE IT NEW), No such file or directory

shmget() successful, id: 20381699
shmat() successful 
$ ./a.out 33
ftok() successful. key = 553976853
shmget() successful, id: 20381699
shmat() successful 

解决方案 - 在聊天后(哇SO有聊天!)讨论:

SOLUTION - after in-chat (wow SO has a chat!) discussion:

最后的问题是,在原来的代码,他正在调用<$ c

At the end the problem was that in the original code he was calling shmctl() later on to tell to detach the segment as the last process detached it, before the other process was attached.

$ c> $ c> shmctl()问题是,这实际上使段是私有的。它的键被标记为0x00000000 by ipcs -m ,不能再被其他进程附加 - 实际上标记为延迟删除。

The problem is that this in fact make the segment private. It's key is marked as 0x00000000 by ipcs -m and cannot be attached anymore by other processes - it's in fact marked for lazy deletion.

这篇关于如何附加到现有的共享内存段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆