Проблемы с запуском программы с использованием общей памяти;иногда ошибка вины;shmmax и shmall имеют к этому какое-то отношение? - PullRequest
0 голосов
/ 20 ноября 2010

HI,

У меня есть программа, в которой мастер обрабатывает N рабочих, которые инвертируют каждую строку изображения, давая в конце инвертированное изображение.Программа использует общую память и семафоры posix, безымянные sems, более конкретно, и я использую shmctl с IPC_RMID, а также sem_close и sem_destroy в функции terminate ().Однако, когда я запускаю программу несколько раз, иногда она вызывает ошибку сегментации и находится в первом shmget.Я уже изменил свое значение shmmax в ядре, но я не могу сделать то же самое со значением shmall, не знаю почему.

Может кто-нибудь помочь мне?Почему это происходит и почему не все время?Код выглядит нормально, дает мне то, что я хочу, эффективно и так ... но иногда мне приходится перезагружать Ubuntu, чтобы иметь возможность запустить его снова, даже если я думаю, что я освобождаю ресурсы.

Пожалуйста, просветите меня!

РЕДАКТИРОВАТЬ:

Вот 3 файла, необходимые для запуска кода + make-файл:
http://pastebin.com/JqTkEkPv
http://pastebin.com/v7fQXyjs
http://pastebin.com/NbYFAGYq

http://pastebin.com/mbPg1QJm

Вы должны запустить его следующим образом ./invert someimage.ppm outimage.ppm (пока протестируйте с небольшим, пожалуйста)

Вот некоторые значения, которые могут быть важны:

$ipcs -lm
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 262144
max total shared memory (kbytes) = 8388608
min seg size (bytes) = 1

$ipcs -ls

------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767

РЕДАКТИРОВАТЬ: ошибка сегмента была решена!Я выделял массив ** в разделяемой памяти, и это было немного странно. Итак, я выделил сегмент только для массива * и вуаля.Если хотите, проверьте новый код и оставьте комментарий.

Ответы [ 2 ]

3 голосов
/ 20 ноября 2010

Если все ваши семафоры sem_t POSIX не имеют названия, вы должны использовать только sem_init и sem_destroy для них и никогда sem_close.

1 голос
/ 20 ноября 2010

Теперь, когда вы разместили свой код, мы можем сказать немного больше.

Не прочитав все подробно, я думаю, что этап очистки вашего main выглядит подозрительно. На самом деле мне кажется, что все ваши рабочие процессы также выполнят эту фазу очистки.

После развилки вы должны более четко различать, что делает main и что делают рабочие. Альтернативы:

  • Ваш основной процесс может просто wait на pid рабочих и только потом делать остальное обработка и очистка.
  • Все рабочие процессы могут вернуться в main после звонка worker.
  • Звоните exit в конце рабочего функция.

Изменить после обновления кода:

Я думаю, что лучшим решением было бы сделать классический wait для всех процессов.

Теперь давайте посмотрим на ваш рабочий процесс. На самом деле они никогда не завершаются, в цикле while (1) нет оператора break. Я думаю, что то, что происходит, когда больше нет работы, которую нужно сделать

  • рабочий застрял в sem_wait(sem_remaining_lines)
  • ваш основной процесс получает уведомление окончание
  • уничтожает sem_remaining_lines
  • рабочий возвращается с sem_wait и продолжается
  • , поскольку mutex3 также уже уничтожено (или, может быть, даже не нанесено на карту) ожидание возврата немедленно
  • теперь он пытается получить доступ к данным, и в зависимости от того, как далеко main процесс получил на уничтожение данных сопоставлено или нет и рабочий вылетает (или нет)

Как видите, у вас там много проблем. Что бы я сделал, чтобы убрать этот беспорядок

  • waitpid до уничтожения общего данные
  • sem_trywait вместо 1 в while (1). Но, возможно, я не совсем понял ваш поток контроля. В любом случае, дайте им условие расторжения.
  • захватить все возвращения из системы функции, в частности sem_t семьи. Они могут быть прерваны IO, так что вы окончательно должны проверьте EINTR на них.
...