Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
 Аватар для UriahHeep
224 / 219 / 77
Регистрация: 24.09.2012
Сообщений: 511
Записей в блоге: 2

Сделать массив из 10 int в разделяемой памяти

04.07.2013, 23:05. Показов 2540. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Хочу сделать массив из 10 int в разделяемой памяти. Доступ из разных процессов от fork().
Так понимаю, 19-20 строки должны сказать сколько памяти выделено, но в выводе получаю что-то типа этого: 134514288.
А на 22-ой строке вываливается с ошибкой сегментации.

Наведите на путь истинный.

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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
 
int main(void) {
 
    pid_t pid;
    int *shm_arr;
 
    int shm_id;
    key_t shm_key;
    struct shmid_ds ds;
 
    shm_key = ftok("qwerty", 1);
    shm_id = shmget(shm_key, 10 * sizeof(int), IPC_CREAT | IPC_EXCL | 0600);
    shm_arr = (int *) shmat (shm_id, NULL, 0);
 
    shmctl(shm_id, IPC_STAT, &ds);
    printf("Allocate size: %d.\n", ds.shm_segsz);
 
    shm_arr[0] = 1;
 
    pid = fork();
    switch (pid) {
        case -1:
            printf("Error in fork().");
            break;
        case 0:
            shm_id = shmget(shm_key, 10 * sizeof(int), 0600);
            shm_arr = (int *) shmat (shm_id, NULL, 0);
            shm_arr[1] = 9;
 
            shmdt (shm_arr);
            break;
        default:
            printf("Parent: %d, %d.\n", shm_arr[0], shm_arr[1]);
 
 
            break;
    }
 
    shmdt (shm_arr);
 
    return EXIT_SUCCESS;
}
Добавлено через 4 часа 59 минут
Так память в размере 4-х байта под int выделяется, но как только указываю 10 * sizeof(int), то errno показывает Invalid argument.
C
1
2
3
4
5
    shm_id = shmget(shm_key, sizeof(int), 0666 | IPC_CREAT);
    if (shm_id == -1) {
        printf("Error shmget: %s.\n", strerror(errno));
        return EXIT_FAILURE;
    }
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.07.2013, 23:05
Ответы с готовыми решениями:

Аська на основе разделяемой памяти
Прогреры и хакеры и им подобные... обращаюсь с особой просьбой: есть мысли по поводу перессылки сообщений через разделяемую память между...

Синхронизация доступа к разделяемой памяти
Когда потоки являются дочерними по отношению к процессу тут все просто - объект мьютекса находится в общей памяти и используя этот объект...

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

3
40 / 37 / 15
Регистрация: 25.10.2012
Сообщений: 112
05.07.2013, 01:36
Начнём с того, что не проверять возвращаемые значения на предмет ошибок - это не просто дурной тон. Это путь к написанию неправильного кода с кучей багов.

Никогда, никогда так не делайте.
Цитата Сообщение от UriahHeep Посмотреть сообщение
C
1
switch (pid) {
switch - это конструкция, которая таит в себе огромное число потенциальных ошибок.
Лучше сделать так:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
pid = fork();
 
if ( -1 == pid)
{
    perror( "fork");
    exit( EXIT_FAILURE);
}
 
if ( !pid)
{
    // дочерний процесс
}
// родительский процесс
Из этих четырёх строчек три - лишнее, и в итоге всё это неправильно.
Цитата Сообщение от UriahHeep Посмотреть сообщение
C
1
2
3
4
shm_id = shmget(shm_key, 10 * sizeof(int), 0600);
shm_arr = (int *) shmat (shm_id, NULL, 0);
shm_arr[1] = 9;
shmdt (shm_arr);
Вы в дочернем процессе зачем-то создаёте ещё один сегмент разделяемой памяти и выполняете подстыковку, в то время как нужно всего лишь воспользоваться уже имеющимся указателем (строка 3).
Цитата Сообщение от UriahHeep Посмотреть сообщение
C
1
shm_arr[1] = 9;
Вы напрасно считаете, что printf обязательно отработает после того, как значение arr[1] станет равным 9. Этого никто не гарантирует. Есть разные способы синхронизации, но в простейшем случае можно просто попросить родительский процесс подождать 1 секунду.
C
1
2
sleep( 1);
printf("Parent: %d, %d.\n", shm_arr[0], shm_arr[1]);
Вот теперь мы дошли до конца. Сегмент-то отстыковали, ну а удалять его кто будет? Если не запросить удаление, то при повторном запуске программы функция shmget() вернёт EEXIST в соответствии с флагами IPC_CREAT | IPC_EXCL. Должно быть вот так.
C
1
2
shmdt ( shm_arr);
shmctl( shm_id, IPC_RMID, NULL);
С описанными выше правками код становится полностью рабочим.
Linux 3.9.8, GCC 4.8.1
2
 Аватар для UriahHeep
224 / 219 / 77
Регистрация: 24.09.2012
Сообщений: 511
Записей в блоге: 2
05.07.2013, 10:55  [ТС]
xanderfomin, спасибо вам.
Внимательнее посмотрел man'ы и поправил:
C
1
shm_key = ftok(__FILE__, 1);
Цитата Сообщение от UriahHeep Посмотреть сообщение
C
1
2
3
shm_id = shmget(shm_key, 10 * sizeof(int), 0600);
shm_arr = (int *) shmat (shm_id, NULL, 0);
shm_arr[1] = 9;
А здесь всё стало ясно после строк: man shmat
After a fork(2) the child inherits the attached shared memory segments. (При исполнении fork(2) дочерний процесс наследует пристыкованные сегменты разделяемой памяти.)

Цитата Сообщение от xanderfomin Посмотреть сообщение
Вы напрасно считаете, что printf обязательно отработает после того, как значение arr[1] станет равным 9. Этого никто не гарантирует. Есть разные способы синхронизации, но в простейшем случае можно просто попросить родительский процесс подождать 1 секунду.
Здесь я с вами согласен полностью, синхронизация нужна и в каких-то моих тестовых версиях использовался sleep.


Цитата Сообщение от xanderfomin Посмотреть сообщение
Никогда, никогда так не делайте.
А вот по поводу этого, ну не знаю... Почему?
man fork говорит:
RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.
Т.е. pid может принимать "три значения": -1 при ошибке, 0 для дочернего процесса и всё остальное для родительского. Где вы здесь видите потенциальные ошибки?
0
40 / 37 / 15
Регистрация: 25.10.2012
Сообщений: 112
06.07.2013, 00:14
Цитата Сообщение от UriahHeep Посмотреть сообщение
Т.е. pid может принимать "три значения": -1 при ошибке, 0 для дочернего процесса и всё остальное для родительского. Где вы здесь видите потенциальные ошибки?
Всё так, и с формальной точки зрения Ваш код верен. Но. Во-первых, какого-либо выигрыша по скорости при трёх ветках Вы от switch не получите. Во-вторых - и это самое главное - стоит Вам случайно не поставить break (ошибка ведь очень частая), как управление "проваливается" к следующей метке, и в итоге получается совсем не то, что ожидалось
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.07.2013, 00:14
Помогаю со студенческими работами здесь

Считать структуру из разделяемой памяти
Добрый день! Есть разделяемый файл. В приложении А в файл запихиваю структуру. В приложении Б считываю эту структуру из файла. Выдается...

Запись и считывание разделяемой памяти
Всем доброго времени суток. Столкнулся с одной проблемой. Есть две программы: 1 создаёт разделяемую память и записывает туда данные, а...

В чем основное преимущество разделяемой памяти
Подскажите в чем основное преимуществоразделяемой памяти

Прогон программ с использованием разделяемой памяти
/* Мы организуем разделяемую память для массива из трех целых чисел. Первый элемент массива является счетчиком числа запусков программы...

Как сохранить данные контейнера в разделяемой памяти
Ищу быстрый способ обмена данными между процессами. Процессы - одинакового типа т.е одна и та же программа и все процессы на одной машине. ...


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru