【问题标题】:Error when trying to attach an used address of shared-memory尝试附加已使用的共享内存地址时出错
【发布时间】:2011-12-20 17:52:14
【问题描述】:

在第二个参数不为 NULL 的情况下使用 shmget 时收到消息“无效参数”。

编译正常,但执行时出现此错误消息。

我整天都被困在这个问题上。希望你能帮我! :)

#include <sys/ipc.h>        
#include <sys/shm.h>        
#include <stdlib.h>     
#include <stdio.h>          


int main()
{
    int idSharedMem;
    int *varSharedMem1;
    int *varSharedMem2;

    /* Create the shared memory */
    idSharedMem = shmget((key_t) 0001, sizeof(int), IPC_CREAT | 0666);

    if (idSharedMem == -1)
    {
        perror("shmget");
    }

    /* Allocate a memory address and attached it to a variable */
    varSharedMem1 = shmat(idSharedMem, NULL, 0);

    if (varSharedMem1 == (int *) -1)
    {
        perror("shmat1");
    }

    /* Sign a value to the variable */
    *varSharedMem1 = 5;

    /* Attach an existing allocated memory to another variable */
    varSharedMem2 = shmat(idSharedMem, varSharedMem1, 0);

    if (varSharedMem2 == (int *) -1)
    {
        /* PRINTS "shmat2: Invalid argument" */
        perror("shmat2");
    }

    /* Wanted it to print 5 */
    printf("Recovered value %d\n", *varSharedMem2);

    return(0);
}

【问题讨论】:

  • 你没有说明哪个函数给你错误。如果shmget -- 在你的平台上'SHMMIN' 的值是多少?如果小于 sizeof(int),则这是记录在案的预期行为。
  • 你能解释第二次调用shmat 应该做什么吗?代码没有任何意义,至少对我来说。而且我无法弄清楚它的目的应该是什么。如果您要再次映射同一段,为什么要传入varSharedMem1?您可以尝试做一些事情。一个最好由varSharedMem2=varSharedMem1; 完成。另一个最好通过传递NULL 作为第二个参数来完成。照原样,我无法弄清楚您希望通过该电话完成什么。
  • @DavidSchwartz echo $SHMMIN 返回空白 :( 我做得对吗?我是 unix 的新手。我知道我可以简单地将一个指针分配给另一个,但我必须使用第二个参数。这是第二个参数应该做的对吗?至少这是我从手册中理解的。感谢您的回答!
  • 你在做什么对吗?我不知道你想做什么。据我所知,您似乎正试图在第一个映射之上创建第二个映射,但这没有任何意义。如果这就是你想要做的,那就不要这样做——它已经被映射了。如果您尝试做其他事情,请解释一下其他事情是什么
  • 谢谢,大卫!这是您所说的,但我可以在@nos 帖子上很好地理解它。如果我做得对,我正在做的正确的事情是回显 SHMMIN 系统变量:p

标签: c linux unix shared-memory


【解决方案1】:

使用shmat(idSharedMem, varSharedMem1, 0);,您尝试将段附加到varSharedMem1 的位置。但是,您之前已在该位置附加了一个段,这将导致 EINVAL。 Linux 提供了一个 SHM_REMAP 标志,您可以使用它来替换以前映射的段。

shmat 手册页:

(Linux 特定的)SHM_REMAP 标志可以在 shmflg 中指定为 表示该段的映射应替换任何现有的 映射范围从 shmaddr 开始并持续 段的大小。 (通常,如果此地址范围中已存在映射,则会导致 EINVAL 错误。)在此 情况下,shmaddr 不能为 NULL。

【讨论】:

  • 嗯!谢谢不!我的工作就像第二个参数是一个使用过的内存地址,它会返回我传递给它的相同地址,就像函数确认可以使用该地址一样。但从你所说的,我可以推断,如果我想指定新的变量地址,我只需要传递第二个参数,并且它只有在它尚未使用时才有效。谢谢:D
  • 让我感到奇怪的是消息 Invalid argument。看起来像是错误的变量类型:/
  • 一些参考,对于那些将要到达这里的人:link
【解决方案2】:

来自 shmat 手册页:

If shmaddr isn't NULL and SHM_RND is specified in shmflg, the attach occurs at the
address equal to shmaddr rounded  down  to  the nearest multiple of SHMLBA. 
Otherwise shmaddr must be a page-aligned address at which the attach occurs.

更多来自 shmat 手册页:

Using shmat() with shmaddr equal to NULL is the preferred, portable way of 
attaching a shared memory segment.

要进行第二次附加,只需:

varSharedMem2 = shmat(idSharedMem, NULL, 0);

【讨论】:

  • 谢谢,佩佩!但是我已经阅读了十几遍手册页,我真的很想传递第二个参数而不是 null。
  • @marcioggs 你可以这样做,但你必须确保你的第二个参数是页面对齐
  • 无论如何,第二次附加会尝试获取空闲内存地址,但这不可能,因为已创建的共享内存只为单个 int 提供足够的空间。
  • 页面对齐是什么意思?去谷歌看看吧。
  • 阅读 linkposix_memalignman page
猜你喜欢
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
相关资源
最近更新 更多