【问题标题】:Linux shmget() function in c++C++ 中的 Linux shmget() 函数
【发布时间】:2013-02-08 17:22:53
【问题描述】:

我正在尝试设置共享内存的 s 段来保存字符串数组。以这个数组为例

string example[] = {"This is", "An Example", "of strings"};

然后我尝试调用 shmget 以便我可以保留适当数量的操作系统共享内存。

shmget(IPC_PRIVATE, sizeOf(example), IPC_CREAT);//我希望这会创建共享内存段

我发现了这个site,上面写着“关键参数是与信号量 ID 相关联的访问值”什么信号量 ID 以及如何创建它。

这使用 g++ -Wall 编译,但我不知道如何检查它是否有。根据 IPC_PRIVATE 所在的 linux 中的 shm 手册,我应该指定“key_t”类型的内容。我的想法是我如何识别共享内存的关键,即指定一个字符串作为共享内存名称,或者指定一个字符串作为 ID 号。

通过阅读手册指出 shmget() 返回一个“shmid”。同样,虽然什么是 shmid,它是 int、string、pointer 还是某种特殊类型,这就是我识别共享内存段的方式吗?另外,如果 shmget() 正在返回某些东西,我不需要将其分配给某些东西吗?

如果您能推荐一个教程或概述,我将不胜感激。除了上面的具体问题,我想要一个从 fork() 命令创建的线程访问共享内存的示例。

我的最终目标是为我的数组中的每个字符串生成一个线程,该线程将执行某种反转。这只是开始使用共享内存和 pthreads 的一个小任务,因为我还没有找到可以完成的教程。

【问题讨论】:

标签: c++ pthreads fork shared-memory


【解决方案1】:

好的,在我解释所有小细节之前,通过共享内存共享数据时非常重要的一件事是您了解您实际放入共享内存的内容。

在你的例子中,你有:

string example[] = {"This is", "An Example ", "of strings"};

您可能没有认真考虑过这一点,但是您认为实际字符串如何存储在“std::string”中?我不知道这种特殊情况下的确切细节,但一个相当典型的实现是这样的[这是简化的,真正的“类字符串”是使用basic_string 类作为基础的模板类声明]。

class string
{
    char *str;
    int len;
}

因此,如果您将example 复制到共享内存中,那么您的共享内存中将包含三个指针和三个整数。这些指针指向一些几乎可以肯定不在共享内存中的内存......显然,“其他进程”中的内存地址不会是你所期望的[好吧,至少如果字符串不是常量并且你的进程在创建字符串之前被分叉 - 但如果字符串是常量和/或在分叉发生时已经存在,那么您真的不需要共享内存,对吧?]

对此的典型解决方案是仅将数据存储在“普通旧数据”的共享内存中(因此没有包含成员函数或指针的对象)。实现此目的的一种方法是“序列化”数据 - 如果您想将数据存储在文件中,您会做同样的事情。

这是使用 g++ -Wall 编译的,但我不知道如何检查是否 它有。根据 IPC_PRIVATE 是 IPC_PRIVATE 的 linux 中的 shm 手册 应该指定“key_t”类型的东西。我的想法是关键 是我识别共享内存的方式,即指定一个字符串作为 共享内存名称或和 in 用于 ID 号。

您可以指定密钥或使用 IPC_PRIVATE(在手册页中将其解释为“不幸的名称”,而“IPC_NEW”会是更好的选择)

通过阅读手册指出 shmget() 返回一个“shmid”。 同样,虽然 shmid 是 int、string、pointer 还是它 某种特殊类型,这就是我识别我的共享的方式吗? 内存段?另外,如果 shmget() 正在返回我不需要的东西 将其分配给某物?

您链接到的网站实际上解释了如何存储shmid

int shmid;

... Several lines of code... 

if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {

我认为这应该足以让您入门。

【讨论】:

  • 不确定,因为我没有测试过,但我认为可以将 std::string 类与自定义分配器和/或放置 new 一起使用,将其数据放入 shm地区……你认为有可能吗?
  • 是的,但要注意共享内存在其他进程中可能有不同的地址,所以如果是这种情况,那么普通旧数据是您唯一的选择。
  • @MatsPetersson 是不是写进程(即最初映射段的那个)把映射地址写入段中偏移量0,那么后续的映射进程就可以解析段内地址了很像ld?换句话说,随后的映射器计算他的映射地址与在段的偏移量 0 处找到的地址之间的字节差 d,并将 d 添加到需要解决的任何地址(指向段内的某个位置)?我这么说是想问你是否应该写“可能是你最好的选择”而不是“是你唯一的选择”?
  • @jeff6times7 当然,有一些方法可以对地址进行编码、计算偏移量等,但它是一个相当复杂的模型,你仍然必须将实际数据存储在共享内存中——如果你有还要重新计算指针,将指针存储在共享内存中是毫无意义的[双关语不是故意的]。从一个位置到另一个位置的偏移量,当然。是的,“仅”可能有点强,但在大多数实际情况下,最好的解决方案是坚持使用纯数据类型和固定长度分配。它只是让生活变得如此轻松。
猜你喜欢
  • 1970-01-01
  • 2014-12-17
  • 1970-01-01
  • 2015-04-08
  • 2014-02-14
  • 2012-04-05
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多