4

使用 C,我正在尝试设置共享内存。我的代码如下所示:

key_t key = ftok("SomeString", 1);
static int *sharedval;
int shmid = shmget(key, sizeof(int), S_IRUSR | S_IWUSR); // less permissions
sharedval = (int *) shmat(shmid, NULL, 0);
*sharedval = 0;

但是,当我运行最后一行时,我遇到了分段错误。调试时,我可以打印“sharedval”,我得到一个内存地址,大概是我得到的内存中的位置。所以我会假设我所要做的就是用*sharedval它来评估它,但显然不是。我应该如何从共享内存中读取?朝着正确的方向前进会很棒。谢谢!

编辑:

another.anon.coward 的输出:

$ ./a.out 
ftok: No such file or directory
shmget: No such file or directory
Trying shmget with IPC_CREAT
shmget success
shmat success
Segmentation fault: 11
4

4 回答 4

7

您的问题可能是给定键没有关联的内存段。在这种情况下,您需要通过传入IPC_CREAT标志来创建一个内存段。shmget请使用perror检查您的错误信息。使用可以试试下面的代码

    #include <stdio.h> //For perror
    ...

    key_t key = ftok("SomeString", 1);
    if ( 0 > key )
    {
       perror("ftok"); /*Displays the error message*/
       /*Error handling. Return with some error code*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("ftok success\n");
    }

    static int *sharedval;
    int shmid = shmget(key, sizeof(int), S_IRUSR | S_IWUSR | IPC_CREAT);
    if ( 0 > shmid )
    {
        perror("shmget"); /*Displays the error message*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("shmget success\n");
    }

    sharedval = (int *) shmat(shmid, NULL, 0);
    if ( 0 > sharedval )
    {
       perror("shmat"); /*Displays the error message*/
       /*Error handling. Return with some error code*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("shmat success\n");
    }
    *sharedval = 0;
    ...
于 2011-09-21T09:24:24.063 回答
2

在现代程序中进行共享内存的正确方法是使用mmapand MAP_SHARED。您可以使用普通文件或使用创建的命名共享内存对象shm_open

于 2011-09-21T06:32:52.940 回答
2

问题是 ftok 需要一个可以传递给 fstat 的现有文件,而不是任意字符串。从手册页:

key_t ftok(c​​onst char* 路径名,int proj_id)

ftok() 函数使用由给定路径名命名的文件的标识(必须引用现有的、可访问的文件)...

一个简单的解决方法是尝试:

int main(int argc, char* argv[])
{
  key_t key = ftok(argv[0], 1);
  ...
}

这也解释了为什么您从 ftok 收到 ENOENT(没有这样的文件或目录)错误。

于 2012-08-08T14:32:18.423 回答
1

如上所述,您的代码缺少错误检查。例如,shmat 指示错误的方式是返回 -1,当它显示为指针时,它看起来像一个 long int - 所以这里发生的事情很好。

具体来说,请注意,代表 File Token 的 ftok() 需要获取 Linux 文件系统上有效文件的路径,以从文件 inode 编号推导出共享内存 ID(它不查看文件内容)。除非您在当前目录中有一个名为 SomeString 的文件,否则这就是此调用失败的原因。

最后但同样重要的是,我真的建议使用 POSIX 共享内存 API 而不是您正在使用的 SySV API。详见 shm_open(3) (http://linux.die.net/man/3/shm_open)

于 2011-09-21T06:37:23.717 回答