【问题标题】:Cannot attach shared memory in shared library无法在共享库中附加共享内存
【发布时间】:2020-10-15 10:07:29
【问题描述】:

我想使用共享库中的共享内存来进行数据交换和套接字操作。
在我的库中,当第一个进程加载共享库时,会在构造函数中创建共享内存。
然后,第二个进程加载共享库,我想附加这个共享内存。
但是第二个进程创建了其他共享内存,尽管密钥是相同的。

这是示例代码。

char* sharedmemory;

__attribute__ ((constructor)) void attach_sharedmemory() {
    key_t key = 10;
    errno = 0
    int seg_id = shmget(key, 1000, IPC_CREAT | IPC_EXCL | 0660);
    if(seg_id == -1){
        if(errno == EEXIST){
            seg_id = shmget(key, 0, 0);
            if(seg_id == -1){
                exit(1);
            }else{
                shared_memory = (char*)(shmat(seg_id, 0, 0));
            }
        }else{
            exit(1);
        }
    }else{
        shared_memory = (char*)(shmat(seg_id, 0, 0));
    }
}

void dllfunction1(){}
void dllfunction2(){}

ipcs 命令结果在这里。 第二个进程的 shmid 总是第一个进程的 shmid + 1。

#result of ipcs
------ Shared Memory Segments --------
key        shmid owner perms bytes nattch status
0x00000XXX 65536 user1 660   1000     1    dest  <--- created first process
0x00000YYY 65537 user1 660   1000     1    dest  <--- created second process

我该如何解决这个问题?

我的环境是 Ubuntu 20.04LTS。 编译好的 GCC。

【问题讨论】:

  • 你试过下面的版本吗?
  • 谢谢!非常感谢您的友好回答。是的,它在一台机器上工作。但是在另一台机器上(这是我要使用的机器),尽管代码相同,问题仍未解决。我一次又一次地尝试并检查了代码。但没有解决……我该怎么办?
  • 欢迎。两台机器上的不同操作系统或版本?尝试运行strace 或调试器并查看shmget()shmat() 之后的返回值和errno。请参阅 ipcs -mipcrm -m。也可以尝试所有不带 IPC_EXCL 的 shmget()
  • 非常感谢。是的。在 WSL 上的 Ubuntu 中取得成功。失败的是真正的 Ubuntu。行。我会尝试你的建议。非常不幸的是,由于我的隐私原因,我无法在 5 天内尝试您的建议。所以,也许 10 月 22 日,我会回答结果。非常感谢你!你是个很善良的人!
  • 是的,我成功了。我错过了我的代码!非常非常感谢你!非常感谢!

标签: c linux shared-libraries shared-memory


【解决方案1】:

调用shmget()的第二个进程由于标志位IPC_EXCL而失败 正如预期的那样;尽管对shmget() 的下一次调用重用了相同的密钥并且 flags 更改为 0(无 IPC_EXCL),大小为 0 导致新段。

通过重用相同的键大小(同样是没有IPC_EXCL的标志),第二个 进程可以获得相同的段ID并附加。下面的示例代码是 在原版的基础上添加了 shmem detach:


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

static void *sharedmemory;
static int seg_id;

__attribute__ ((constructor))
void attach_shmem(void)
{
    key_t key = 10;
    size_t size = 1000;
    seg_id = shmget(key, size, IPC_CREAT | IPC_EXCL | 0660);

    if ((seg_id == -1) && (errno == EEXIST))
        seg_id = shmget(key, size, 0);
    if (seg_id == -1)
        exit(1);
    sharedmemory = shmat(seg_id, NULL, 0);
}

__attribute__ ((destructor))
void detach_shmem(void)
{
    (void) shmdt(sharedmemory);
}

【讨论】:

  • 请注意,调用printf() 可以更改errno 的值,因此您需要调用printf() 之前保存它并使用该值。
  • 修剪的测试内容
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
  • 1970-01-01
  • 2017-03-22
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多