Блокировка механизмов для непротиворечивости общей памяти

Я разрабатываю механизм для обмена данными между двумя или больше процессами с помощью общей памяти на Linux. Проблема немного находится на одном уровне управления совместным выполнением, требуется, чтобы поддерживать целостность данных на самой общей памяти, и поскольку я - specting, который когда-то или другой мой процесс мог быть уничтожен/разрушен, общие механизмы блокировки' не работают, потому что они могли, оставил память в "заблокированном" состоянии и прямо после того, как смерть, делая другие процессы подвесила ожидание блокировки, которая будет выпущена.

Так, проводя некоторое исследование, я нашел, что семафоры System V имеют флаг под названием SEM_UNDO, который может вернуться состояние блокировки, когда программа перестала работать, но это, как гарантируют, не будет работать. Другая опция состоит в том, чтобы контролировать PID от всех процессов, которые могли бы использовать общую память и сделать некоторое управление ими, если что-то противное происходит, но я не так уверен, могло ли это быть правильным подходом к моей проблеме.

Какие-либо идеи??:)

Править: в целях объяснения для нашего приложения нужен некоторый механизм IPC с самой маленькой возможной задержкой. Так, я открыт для механизмов, которые могут обработать это требование также.

9
задан scooterman 18 June 2010 в 16:44
поделиться

5 ответов

Мне было бы любопытно узнать, из какого источника вы узнали, что SEM_UNDO не гарантированно работает. Я не слышал этого раньше. Кажется, я помню, что читал статьи, в которых утверждалось, что SYSV IPC в linux вообще глючит, но это было довольно давно. Мне интересно, не является ли ваша информация просто артефактом прошлого.

Другая вещь, которую нужно учитывать (если я правильно помню), это то, что семафоры SYSV имеют возможность сообщить вам PID последнего процесса, который выполнил операцию семафора. Если вы зависли, вы должны быть в состоянии запросить, жив ли еще процесс, удерживающий блокировку. Поскольку любой процесс (не только тот, который держит блокировку) может манипулировать с семафором, вы можете осуществлять контроль таким образом.

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

1
ответ дан 4 December 2019 в 22:27
поделиться

Есть только несколько вещей, которые гарантированно будут устранены в случае сбоя программы. Единственное, что мне здесь приходит в голову, - это количество ссылок. Дескриптор открытого файла увеличивает количество ссылок базового inode, а соответствующее закрытие уменьшает его, включая принудительное закрытие при сбое программы.

Таким образом, все ваши процессы могут открывать общий файл (не помните, работает ли он для сегментов разделяемой памяти), и вы можете инициировать какой-то сигнал тревоги, если счетчик уменьшится, а этого не должно быть. Например, вместо простого ожидания ваши процессы могут выполнять timedwait (например, на секунду) в цикле и опрашивать счетчик ссылок, который будет предупрежден, когда что-то идет не так.

2
ответ дан 4 December 2019 в 22:27
поделиться

Вы можете использовать мьютекс pthread в общей памяти pthread_mutexattr_setpshared ( http://linux.die.net/man/3/pthread_mutexattr_setpshared )

Также вы можете попробовать использовать futexes напрямую, смотрите http://people.redhat.com/drepper/futex.pdf и http://lxr.linux.no/#linux+v2.6.34/Documentation/robust-futexes.txt и http://www.kernel.org/doc/man-pages/online/pages/man7/futex.7 .html и http://www.kernel.org/doc/man-pages/online/pages/man2/futex.2.html Особенно второй, поскольку там говорится о том, как заставить ядро освободить его, когда процесс, держащий его, умирает.

Также я думаю, что можно сделать pthreads locks/CVs надежными, что является лучшей идеей, поскольку тогда все, что нужно для работы с надежными замками, будет сделано за вас (в даже отдаленно современном дистрибутиве это должно быть использование надежных futexs, описанных в http://lxr. linux.no/#linux+v2.6.34/Documentation/robust-futexes.txt для pthread_mutex IIRC, поскольку он уже давно в ядре, но вы можете убедиться, что вам не нужно ничего делать, чтобы сделать ваш pthread_mutex надежным)

.
1
ответ дан 4 December 2019 в 22:27
поделиться

Когда вы заявили, что семафоры не могут быть чисто Обработка процессов меня немного удивила. Такая поддержка кажется довольно важной! Глядя на страницу руководства semop как в моей системе ubuntu 10.4, так и в Интернете здесь , кажется, можно предположить, что все должно быть в порядке. Надеюсь, память, используемая для хранения счетчика SEM_UNDO, хранится в пространстве ядра и, следовательно, защищена от ошибочной записи в память.

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

1
ответ дан 4 December 2019 в 22:27
поделиться

Итак, проведя небольшое исследование, я обнаружил, что семафоры System V имеют флаг под названием SEM_UNDO, который может вернуть состояние блокировки в случае сбоя программы, но это не гарантирует работы.

SEM_UNDO разблокирует семафор в случае сбоя процесса. Если процессы аварийно завершились из-за повреждения разделяемой памяти, семафоры ничего не могут сделать для вас. ОС не может отменить состояние разделяемой памяти.

Если вам нужно иметь возможность откатить состояние разделяемой памяти, вы должны реализовать что-то самостоятельно. Я видел по крайней мере две модели, которые этим занимаются.

Первая модель перед изменением чего-либо в разделяемой памяти делала снимок структуры, сохраняя ее в списке в разделяемой памяти. Если какой-либо другой процесс смог получить блокировку, а список не был пуст, он отменял все, что могло быть изменено в аварийном процессе.

Вторая модель состоит в том, чтобы делать копии структур shm в локальной памяти и держать блокировку заблокированной для всей транзакции. Когда транзакция фиксируется, перед снятием блокировки просто скопируйте структуры из локальной памяти в общую память. Вероятность сбоя приложения во время копирования ниже, а вмешательство внешних сигналов можно заблокировать с помощью sigprocmask () . (Блокировку в этом случае лучше хорошо разделить по данным. Например, я видел тесты с набором из 1000 блокировок для 10 миллионов записей в shm, к которым обращались 4 параллельных процесса.)

3
ответ дан 4 December 2019 в 22:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: