Не удается подключить общую память в общей библиотеке

#c #linux #shared-libraries #shared-memory

#c #linux #общие библиотеки #разделяемая память

Вопрос:

Я хотел бы использовать общую память в общей библиотеке для обмена данными и управления сокетом.
В моей библиотеке, когда первый процесс загружает общую библиотеку, общая память создается в конструкторе.
Затем второй процесс загружает общую библиотеку, я хочу подключить эту общую память.
Но второй процесс создает другую общую память, хотя ключ тот же.

Это пример кода.

 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.

Комментарии:

1. вы пробовали версию ниже?

2. Спасибо! Большое вам спасибо за ваш любезный ответ. Да, это сработало на одной машине. Но на другой машине (это машина, которую я хочу использовать) проблема не была решена, несмотря на тот же код. Я пробовал снова и снова и проверял код. Но не решается… Как я могу сделать?

3. Добро пожаловать. Разные ОС или версии на 2 машинах? Попробуйте запустить strace или отладчик и просмотреть возвращаемые значения и errno после shmget() и shmat() . См ipcs -m . И ipcrm -m . Также попробуйте все shmget() без IPC_EXCL.

4. Чем вы очень довольны. ДА. Успешно реализован в Ubuntu на WSL. Сбой — это настоящая Ubuntu. ОК. Я попробую ваш совет. И, к сожалению, я не могу воспользоваться вашим советом в течение 5 дней из-за моей частной причины. Итак, возможно, 22 октября я отвечу на результат. Большое вам спасибо! Вы очень добрый человек!

5. Да, я преуспел. Я пропустил свой код! Большое вам спасибо! Я очень ценю!

Ответ №1:

Второй вызов процесса shmget() завершается с ошибкой из-за бита флага IPC_EXCL, как и ожидалось; хотя при следующем вызове shmget() повторно использовался тот же ключ, и флаги изменились на 0 (без IPC_EXCL), размер был равен 0, что привело к созданию нового сегмента.

Повторно используя тот же ключ и размер (снова флаги без IPC_EXCL), второй процесс может получить тот же идентификатор сегмента и присоединить. Приведенный ниже пример кода основан на оригинале с добавлением отсоединения shmem:


 #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) amp;amp; (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);
}
  

Комментарии:

1. Обратите внимание, что вызов printf() может изменить значение errno , поэтому вам нужно сохранить его перед вызовом printf() и использовать это значение.

2. тестовый материал обрезан