【问题标题】:shmget previously created memory segment failsshmget 先前创建的内存段失败
【发布时间】:2014-05-26 19:41:17
【问题描述】:

我正在尝试学习 IPC UNIX API,特别是共享内存。我创建了这个尝试访问共享内存段或创建一个的小程序。

这就是我的工作:

gcc -Wall -Wextra *.c
# in one terminal
./a.out
# in another
/a.out

您可以在源代码中看到的shared.mem 文件存在于我启动可执行文件的同一目录中。

但是,我似乎从未真正访问过以前创建的共享内存段(错误是“没有这样的文件或目录”)。我总是创建一个新的 - 正如通过 ipcs 命令行看到的那样,即使 IPC 密钥保持不变。

我做错了什么?

以下是我使用的代码,供参考。它至少可以在 Linux 上编译。

#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define exit_error(what) exit_error_func(what, __FILE__, __LINE__)

#define SHM_SIZE (64)
#define UNUSED(x) (void)(x)

void    *shm_addr = NULL;

void    exit_error_func(const char *what, const char *file, int line)
{
    fprintf(stderr, "Error in %s at line %d: %s. Reason: %s.\n", file, line, what, strerror(errno));
    exit(1);
}

void    sigint_handler(int sig)
{
    shmdt(shm_addr);
    UNUSED(sig);
}

int main(void)
{
    key_t           ipc_key;
    int             shm_id;

    if ((ipc_key = ftok("shared.mem", 1)) == -1)
        exit_error("could not get IPC key");
    printf("IPC key is %d\n", ipc_key);
    if ((shm_id = shmget(ipc_key, SHM_SIZE, 0600)) == -1)
    {
        printf("could not get SHM id, trying to create one now\n");
        if ((shm_id = shmget(ipc_key, SHM_SIZE, IPC_EXCL | IPC_CREAT | 0600)) == -1)
            exit_error("could not create or get shared memory segment");
        else
            printf("created SHM id\n");
    }
    else
        printf("got already existing SHM id\n");
    printf("SHM id is %d\n", shm_id);
    if ((shm_addr = shmat(shm_id, NULL, 0)) == (void *)-1)
        exit_error("could not attach to segment");
    signal(SIGINT, sigint_handler);
    if (shmctl(shm_id, IPC_RMID, NULL) == -1)
        exit_error("could not flag shared memory for deletion");
    printf("SHM flagged for deletion\n");
    while (1)
        sleep(1);
    return (0);
}

【问题讨论】:

  • 您从程序调用的哪一行得到的准确错误是什么?
  • 第一次调用shmget 失败并将errno 设置为ENOENT
  • 嗯,奇怪,因为(正如你所说)我们有:#define ENOENT 2 /* No such file or directory */ 你的代码在我的 linux 上完美运行......尝试删除并重新创建 shared.mem(触摸 shared.mem)。当您说“您可以在源代码中看到的 shared.mem 文件存在于我启动可执行文件的同一目录中”时。我想你的意思是 a.out 和 shared.mem 在同一个目录中?
  • 是的,shared.mema.out 位于同一文件夹中。我已经尝试重新创建它,但第一次调用shmget 总是失败。我总是得到这样的东西(在下面添加了 errno return 和 `perror):pastebin.com/ufVrpawh
  • 出于某种我不明白的原因,如果我删除对shmctl 的调用,它会起作用。也许我需要在完成最后一个shmdt 后标记删除?这将需要更多技巧才能知道哪个进程是最后一个通过shmctl(..., IPC_STAT, ...) 分离的进程。

标签: linux unix ipc


【解决方案1】:

似乎无法shmget 标记为删除的共享内存段。因此,一旦没有进程需要shmget,就必须将共享内存段标记为删除。

免责声明:我不是 UNIX 专家。虽然建议的解决方案对我有用,但我仍在学习,无法保证此处提供的信息的准确性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-21
    • 2015-08-27
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 2018-02-26
    相关资源
    最近更新 更多