Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
14 / 7 / 2
Регистрация: 25.03.2014
Сообщений: 90

Изменить размер у POSIX shared memory сегмента

10.07.2016, 21:26. Показов 2397. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Подскажите, пожалуйста, как изменить размер уже выделенного сегмента разделяемой памяти?

Вот так выделяю:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Размер динамического массива в разделяемой памяти
uint_fast64_t facts_size = 1;
// Массив
float *array = NULL;
 
// Дескриптор для разделяемой памяти
int shm = 0;
 
// Выделение разделяемой памяти
array = shm_alloc(&size,name,&shm);
 
float *shm_alloc(uint_fast64_t *size, const char *name, int *shm){
 
    int mode = O_CREAT|O_RDWR;
    float *array = NULL;
 
    // Имя области разделяемой памяти
    const char *shared_memory_object_name = name;
 
    // Время для замера длительности в миллисекундах
    long long remember_the_time = 0;
 
    printf("Резерование разделяемой памяти");
    fflush(stdout);
    remember_the_time=time_ms();
 
    if (((*shm) = shm_open(shared_memory_object_name, mode, 0600)) == -1) {
        fprintf(stderr, "shm_open error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
 
    if (ftruncate((*shm), (*size)*sizeof(float)) == -1){
        fprintf(stderr, "ftruncate error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
 
    array = mmap(0, (*size)*sizeof(float), PROT_WRITE|PROT_READ, MAP_SHARED, (*shm), 0);
    if (array == (float*)-1) {
        fprintf(stderr, "mmap error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
    printf(" завершено за %lldms\n",time_ms()-remember_the_time);
 
    // Возврат значения
    return(array);
}
Попытка изменить размер завершается Segmentation fault

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
size++;
shm_realloc(array,&size,&shm);
 
void shm_realloc(float *array, uint_fast64_t *size, int *shm){
 
    if (ftruncate((*shm), (*size)*sizeof(float)) == -1){
        fprintf(stderr, "ftruncate error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
 
    array = mmap(0, (*size)*sizeof(float), PROT_WRITE|PROT_READ, MAP_SHARED, (*shm), 0);
    if (array == (float*)-1) {
        fprintf(stderr, "mmap error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.07.2016, 21:26
Ответы с готовыми решениями:

Организовать доступ к списку из любого, независимо запущенного скрипта
В версии языка 3.8 есть возможность использовать общую память. Вот таким образом можно организовать доступ к списку из любого, независимо...

Shared memory
Микроконтроллер загружает необходимую информацию в shared memory по заранее известным адресам. Как считать/получить доступ к этой инфе из...

Shared memory does not exist
Доброе утро! Столкнулся с такой проблемой, Oracle 8.1, лет 20 крутится около 18 схем и начала выпадать соответствующая ошибка, хотя все...

7
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
12.07.2016, 08:48
Может проблема в том, что к памяти мы получаем доступ через mmap, скорее всего перед изменением размера надо снять привязку адрес<=>дескриптор через munmap и только потом менять размер через ftruncate. Причём munmap придётся делать всем процессам...
0
14 / 7 / 2
Регистрация: 25.03.2014
Сообщений: 90
12.07.2016, 09:39  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
Причём munmap придётся делать всем процессам...
На буржуинских сайтах нашёл упоминание подобного механизма как наихудшего варианта.

Вот ещё интересные ссылки с использованием mremap, но повторить как в описано не удалось. Тот же Segmentation fault:
1. "mremap function failed to allocate new memory"

2. "Linux mremap without freeing the old mapping?"

ЧЯДНТ?

C
1
2
3
4
5
6
7
8
9
10
void shm_realloc(float *array, uint_fast64_t *new_array_size, int *shm){
 
    uint_fast64_t old_array_size = new_array_size-1;
 
    if (ftruncate((*shm), (*new_array_size)*sizeof(float)) == -1){
        fprintf(stderr, "ftruncate error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
    mremap(array,old_array_size*sizeof(float),(*new_array_size)*sizeof(float), 4000, MREMAP_MAYMOVE);
}
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
12.07.2016, 09:48
А mremap что возвращает(в случае ошибки -1 должно быть)? errno что показывает в случае ошибки?
0
14 / 7 / 2
Регистрация: 25.03.2014
Сообщений: 90
12.07.2016, 22:18  [ТС]
drfaust, спасибо за подсказку. Действительно, нашёл ошибки, но снова запнулся. Запустил в дебагере. Как только array_size переваливает за 2048, то mremap назначает указателю array адрес 0xFFFFFFFFFFFFF и в errno можно увидеть такое сообщение об ошибке:


mremap error: Bad address


C
1
2
3
4
5
6
7
8
9
10
11
12
void shm_realloc(float *array, uint_fast64_t *array_size, int *shm){
 
    if (ftruncate((*shm), (*array_size)*sizeof(float)) == -1){
        fprintf(stderr, "ftruncate error: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
    array = mremap(array,((*array_size)-1)*sizeof(float),(*array_size)*sizeof(float),MREMAP_MAYMOVE);
    if(array == MAP_FAILED)
    {
        fprintf(stderr, "mremap error: %s\n", strerror(errno));
    }
}
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
13.07.2016, 09:37
Если чем поможет:
EFAULT
"Ошибка сегментирования" ("Segmentation fault"). Один из адресов в области с old_address по old_address+old_size не подходит для этого процесса. Сообщение об этой ошибке будет выдано также в случае, если вся эта область отражена, но эти отражения разных типов.
Добавлено через 5 минут
Ошибка не совсем понятна по описанию...

Какие параметры в ядре прописаны?
Bash
1
sysctl | grep kernel.shm
0
14 / 7 / 2
Регистрация: 25.03.2014
Сообщений: 90
22.07.2016, 14:18  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
Ошибка не совсем понятна по описанию...
Если честно, то смутно представляю весь механизм разделения памяти. Просто последовательный набор каких-то магических действий (shm_open,ftruncate,mmap). Однако, сама по себе разделяемая память из моих примеров работает корректно, но это не касается изменения размера уже выделенной области. Документация скудна и и написана недоступно для понимания. Модели примеров в книгах крайне примитивны и нигде, подчеркну нигде нет работающих примеров с изменением размера у shared memory. Сайты буржуинов пестрят подобными вопросами как у меня, но вменяемых ответов нет. Есть только утверждение в документации на POSIX shared memory, что изменять размер можно. Безуспешно месяц ищу ответ на вопрос "КАК?". Пока сделал костыль с записью сначала в обычную кучу, изменение размера через realloc и уже на финальной стадии (когда известен размер) - выделение и копирование в разделяемую область. Но мой перфекционизм не даёт смериться с убогостью решения. Коллеги, спасите мою нервную систему! Крик души:

Будьте любезны, поделитесь работающим примером выделения и последующего изменения памяти у shared memory!
0
14 / 7 / 2
Регистрация: 25.03.2014
Сообщений: 90
09.05.2017, 22:52  [ТС]
Работающий пример:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/* main.c */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
 
int main(void)
{
    size_t size_of_mem = 1024;
    int fd = shm_open("/myregion", O_CREAT | O_RDWR,
                      S_IRWXO | S_IRUSR | S_IWUSR);
    if (fd == -1)
    {
        perror("Error in shm_open");
        return EXIT_FAILURE;
    }
 
    if (ftruncate(fd, size_of_mem) == -1)
    {
        perror("Error in ftruncate");
        return EXIT_FAILURE;
    }
 
    void *shm_address = mmap(0, size_of_mem,
                             PROT_READ | PROT_WRITE | PROT_EXEC,
                             MAP_SHARED, fd, 0);
    if (shm_address == MAP_FAILED)
    {
        perror("Error mmapping the file");
        return EXIT_FAILURE;
    }
 
    /* Increase shard memory */
    for (size_t i=0; i<1024; ++i){
 
        /* Does 8 align memory page? */
        size_t new_size_of_mem = 1024+(8*i);
 
        if (ftruncate(fd, new_size_of_mem) == -1)
        {
            perror("Error in ftruncate");
            return EXIT_FAILURE;
        }
 
        /*
           mremap() works with  aligned memory pages.
           How to properly increase shared memory in this case?
        */
        void *temp = mremap(shm_address, size_of_mem, new_size_of_mem, MREMAP_MAYMOVE);
        if(temp == (void*)-1)
        {
            perror("Error on mremap()");
            return EXIT_FAILURE;
        }
 
        shm_address = temp;
 
        size_of_mem = new_size_of_mem;
 
    }
 
    return 0;
}
Bash
1
gcc -pipe -Wall -Wextra -Wpedantic -Wshadow -march=native -std=c11 -o ./main ./main.c -lrt
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.05.2017, 22:52
Помогаю со студенческими работами здесь

Не могу разобраться с Shared memory
Доброго времени суток, возникла проблема при использовании разделяемой памяти. При написании 2 небольших программ взаимодействующих с...

Creating Named Shared Memory
Здравствуйте. Пытаюсь освоить работу с общей памятью двух разных программ, используя FileMapping, всё делаю как в ссылке, но в первой...

Pipe, fork, shared memory
Доброго времени суток. Помогите пожалуйста написать программу: Процесс читает с клавиатуры и пишет в пайп, его ребенок читает из этого...

Insufficient space for shared memory file
Ставлю Jira на удаленный сервер и получаю такое сообщение сразу после запуска бинарника: Java HotSpot(TM) 64-Bit Server VM warning:...

COM-объект..клиент-сервер..shared memory
передо мной поставлена задача: что то в таком стиле, весь текст не привожу... вопрос: где про приведенное ниже можно почитать? ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru