LINUX.ORG.RU

[System V] Семафоры и Ко


0

2

Мне понадобилось как-то на неделе написать кроссплатформенный семофор (именованный, то есть для межпроцессной синхронизации) со всеми вытекающими. После некоторого анализа того, что и где имеется, решил остановиться на интерфейсе System V (более распространенный, а вояки наши любят использовать что-нибудь подревнее) для unix-систем, для Windows-систем, конечно же, использовать родной API. В итоге все получилось и работает, но у меня возникло несколько вопросов и наблюдений.

То, что API System V неуклюж и несколько перегружен - не вызывает сомнений, хотя, через денек, начинаешь привыкать. Но проблемы вытекают напрямую из этой самой System V. Во-первых, надо создавать для каждого IPC-объекта (семафор, разделяемая память, с другим еще не возился) свой файл и по нему генерить заветный key_t. Почему нельзя было использовать обычную буквенную последовательность, как это, например, сделано в Windows? Да, я знаю про POSIX-интерфейс к IPC, но и там жизнь не легче. Стандартом де-факто в мире UNIX является System V, поэтому от этого и решено было отталкиваться. Поэтому приходиться следить за созданным файлом. Это раз.

У семафора есть такая проблема, что им владеет, фактически, система, а не процессы. То есть, если вдруг процессы сегфолтнутся и семафор будет в этот момент в залоченном состоянии, то при следующем запуске приложения и обращения к семафору я опять получу уже залоченный семафор. Например в Windows семафором «владеют» процессы, и как только все процессы завершатся или «отпустят» семафор, он удаляется. Все просто и надежно. Есть ли какой-то Ъ-вэй решить этот косяк в UNIX-системах? Только, пожалуйста, без костылей типа мастер-процесса следящего за другими, или запускать один процесс всегда первым и т.д. Есть ли что-нибудь готовое на системном уровне? Только не надо говорить про SEM_UNDO - связанные с этим косяки всем известны, равно как и системно-зависимая реализация.

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

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

★★★★

Я семафорами конечно не пользовался, но они есть в Qt. Может найдешь в ихней обертке то, что тебе нужно без костылей.

ShTH
()

> семофор

facepalm.jpg

решил остановиться на интерфейсе System V

вояки наши любят использовать что-нибудь подревнее)

Мыши_и_кактус.avi.bz2 (4.7G)

Есть ли какой-то Ъ-вэй решить этот косяк в UNIX-системах?

Не использовать SysV IPC. То, что они говно, давно известно (их же придумали люди, которые в Unix ничего не смыслили).

tailgunner ★★★★★
()

> Стандартом де-факто в мире UNIX является System V

забавно. а я думал, этим давно никто не пользуется

если вдруг процессы сегфолтнутся и семафор будет в
этот момент в залоченном состоянии

robust futex, may be. но только в linux.

idle ★★★★★
()
Ответ на: комментарий от Nakgidveef

> Сегфолт можно перехватить и освободить семафоры.

Это ненадёжно, сегфолтнуться можно так, что пикнуть не успеешь, не то что семафоры освободить. Ну и KILL может настигнуть вдруг, мало ли.

const86 ★★★★★
()
Ответ на: комментарий от const86

>> Сегфолт можно перехватить и освободить семафоры.

Это ненадёжно

А где капитанская шапка?

pathfinder ★★★★
()
Ответ на: комментарий от ShTH

>>Т.е. я предлагаю посмотреть сорцы.

Я посмотрел их давно - там есть костыль в виде параметра Open или Create - то есть либо просто открыть семафор, либо открыть и проинитить заданным значением. Причем даже в доке откровенно написано, что этот параметр работает только в linux. То есть там ничего лучшего не придумали и их семафоры тоже подвержены сабжевым проблемам.

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от pathfinder

>>Может и дурной совет, но может попробовать использовать flock?

Блокировать можно либо мягко, либо жестко. При мягкой блокировке любой левый юзер может снести файл. При жесткой, опять же, появляется проблема с сегфолтом.

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от tailgunner

>>facepalm.jpg

А если я у тебя найду?

Мыши_и_кактус.avi.bz2 (4.7G)

В данном случае, не я диктую условия. Там любят и QNX4 погонять, и солярку мохнатую.

Не использовать SysV IPC. То, что они говно, давно известно (их же придумали люди, которые в Unix ничего не смыслили).

Я не спорю, что оно говно и спроектировано через одно место. Но посиксовые семафоры не лучше - они также остаются в /dev/shm после сегфолтов. Так что тогда использовать?

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от idle

>>забавно. а я думал, этим давно никто не пользуется

Увы, но другого нету.

robust futex, may be. но только в linux.

Спасибо, почитаю.

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от MuZHiK-2

>При мягкой блокировке любой левый юзер может снести файл

Это ещё ничего. Любой левый юзер может снести вообще всю систему. Эта проблема так же решается либо мягко, либо жестко.

pathfinder ★★★★
()
Ответ на: комментарий от MuZHiK-2

>>facepalm.jpg

А если я у тебя найду?

А если нет?

Мыши_и_кактус.avi.bz2 (4.7G)

В данном случае, не я диктую условия.

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

Там любят и QNX4 погонять, и солярку мохнатую.

Насколько я знаю, даже в QNX4 есть нити и сокеты.

P.S. Историческая справка: SysV IPC были придуманы для SVR2, когда единственным способом распараллелить работу в Unix были процессы, а сокеты были BSD-расширением. Сейчас и нити, и сокеты - стандарт.

tailgunner ★★★★★
()
Ответ на: комментарий от MuZHiK-2

Может и дурной совет, но может попробовать использовать flock?

Блокировать можно либо мягко, либо жестко. При мягкой блокировке любой левый юзер может снести файл. При жесткой, опять же, появляется проблема с сегфолтом.

Проблем с сегфолтом у flock нет. Я когда-то специально проверял разные варианты межпроцессовых блокировок, и остановился именно на shm + flock.

Deleted
()
Ответ на: комментарий от pathfinder

flock

Уже предлагали. Он не хочет этот кактус.

У этого кактуса колючки мягкие и вкусные =).

Deleted
()
Ответ на: комментарий от Deleted

>Проблем с сегфолтом у flock нет. Я когда-то специально проверял разные варианты межпроцессовых блокировок, и остановился именно на shm + flock.

А скорость работы не тестировал? А то мне интересно как с производительностью у flock?

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

>>Это ещё ничего. Любой левый юзер может снести вообще всю систему. Эта проблема так же решается либо мягко, либо жестко.

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

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от MuZHiK-2

>Lock-файл не спасет. Если я не ошибаюсь, то есть два процесса откроют его, потом один залочит, а другой закроет, то локи пропадают, не?

ЩИТО?!!

pathfinder ★★★★
()
Ответ на: комментарий от tailgunner

>>А если нет?

Я буду хорошо искать.

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

Сейчас это не играет роли. Сейчас мне интересно, что использовать вместо семафоров System V. Выходит, что ничего и нету.

P.S. Историческая справка: SysV IPC были придуманы для SVR2, когда единственным способом распараллелить работу в Unix были процессы, а сокеты были BSD-расширением. Сейчас и нити, и сокеты - стандарт.

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

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от MuZHiK-2

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

Сейчас это не играет роли.

Итеративная разработка, все дела.

Ну разделяемая память будет всяко быстрее сокетов, не?

да. Но на твоих объемах это неважно, а для реально больших объемов можно сделать out-of-line передачу через, например, mmap-ный файл.

Тут процесс разработки поставлен так, что часть делает какое-то совершенно другое НИИ и на нитками не получится с ними стыковаться.

Мужик, ты попал. Придумай протокол и требуй от них сокеты любыми способами.

но там собираются (не точно, но может быть) ставить потом часть софта на какую-то железку, где сокетов может не быть в принципе (хз что это)

Железка? Какого типа и как ты с железкой общую память организуешь?

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

Именованные пайпы или безымянные? Потому что именованные - это те же сокеты, а безымянные не подойдут в случае железки.

tailgunner ★★★★★
()
Ответ на: комментарий от pathfinder

>>ЩИТО?!!

Да, я ошибся, не два процесса, а два потока: http://en.wikipedia.org/wiki/File_locking, там в разделе с проблемами описано. Там и проблемы с файлухами сетевыми. Я к тому, что решение в файлом куда менее универсальнее семафора и порождает свои проблемы. Хочется чего-то изящного, как на винде.

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от pathfinder

Проблем с сегфолтом у flock нет. Я когда-то специально проверял разные варианты межпроцессовых блокировок, и остановился именно на shm + flock.

А скорость работы не тестировал? А то мне интересно как с производительностью у flock?

Лично я не тестировал. Но в качестве пруфа достаточной производительности может послужить pulseaudio (а возможно и jack) - там клиенты с сервером в пределах одной машины взаимодействуют именно через разделяемую память и файловые блокировки на ней. Правда для блокировок используется не flock, а fcntl, но не суть важно.

Deleted
()
Ответ на: комментарий от MuZHiK-2

Тут русским духом пахнет

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

%) Я так понял ты в коммерческой организации работаешь, а раздолбайство, как в госструктуре. Как можно писать софт под какую то непонятную железку? При том совершенно непонятно, что там будет? Чего не будет?

Жесть какая-то. Надеюсь вам дали много времени и средств, чтобы родить эту неведомую зверушку.

pathfinder ★★★★
()
Ответ на: комментарий от tailgunner

>>да. Но на твоих объемах это неважно, а для реально больших объемов можно сделать out-of-line передачу через, например, mmap-ный файл.

А где-нибудь можно почитать про то, что такое «передача out-of-line»?

Мужик, ты попал. Придумай протокол и требуй от них сокеты любыми способами.

Я уже давно понял, что попал с теми ребятами, буду пытаться пробивать начальство. Правда там много упертых старперов, будет тяжело.

Железка? Какого типа и как ты с железкой общую память организуешь?

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

Именованные пайпы или безымянные? Потому что именованные - это те же сокеты, а безымянные не подойдут в случае железки.

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

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от Deleted

>Но в качестве пруфа достаточной производительности может послужить pulseaudio (а возможно и jack)

:) О,нормальный пруф. Я серьезно.

pathfinder ★★★★
()
Ответ на: Тут русским духом пахнет от pathfinder

>>%) Я так понял ты в коммерческой организации работаешь, а раздолбайство, как в госструктуре.

Да, коммерческая, но настолько приближена к госраспилам и тому подобному, что бардак прям как в самих госструктурах :)

Как можно писать софт под какую то непонятную железку? При том совершенно непонятно, что там будет? Чего не будет?

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

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от pathfinder

А хотя стоп. Возможно я заблуждаюсь, и это плод моего больного воображения...

/me ушёл ковырять исходники pulseaudio

Deleted
()
Ответ на: комментарий от MuZHiK-2

>>да. Но на твоих объемах это неважно, а для реально больших объемов можно сделать out-of-line передачу через, например, mmap-ный файл.

А где-нибудь можно почитать про то, что такое «передача out-of-line»?

Ы. Это вообще-то настолько простая вещь, что описания я даже не встречал :) Вкратце: создается файл, мапится двумя процессами, и дальше они обмениваются токеном (в простейшем случай - байтом с неважно каким значением). Тот процесс, у которого токен, имеет право на доступ к файлу, другой - ждет возвращения токена. Собственно, это всё; схема обобщается и на случай нескольких файлов.

Правда там много упертых старперов, будет тяжело.

Опыт показывает, что старперы предпочитают простые вещи типа обмена Си-структрами по сокету.

Железка? Какого типа и как ты с железкой общую память организуешь?

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

То есть «железка» - это компьютер в сети? Там будут сокеты. А если и не будет (что практически исключено), будешь ловить Ethernet-пакеты в PACKET-сокет :)

tailgunner ★★★★★
()
Ответ на: комментарий от Deleted

Блин, похоже я ошибся. Посыпаю голову пеплом. Всё, что я выше сказал про производительность flock - полностью неподтверждённая информация!

=(

Deleted
()
Ответ на: комментарий от tailgunner

>Ы. Это вообще-то настолько простая вещь, что описания я даже не встречал :) Вкратце: создается файл, мапится двумя процессами, и дальше они обмениваются токеном (в простейшем случай - байтом с неважно каким значением). Тот процесс, у которого токен, имеет право на доступ к файлу, другой - ждет возвращения токена. Собственно, это всё; схема обобщается и на случай нескольких файлов.

Я не понял. И чем это лучше System V semaphore. Просрали токен при падении процесса по segfault и все, система висит?

pathfinder ★★★★
()
Ответ на: комментарий от tailgunner

Ага, что-то меня понесло не туда. Причём фиг знает откуда залезли эти тараканы в мою голову. Походу сказывается то, что я последнюю неделю сплю по два часа в сутки...

Deleted
()
Ответ на: комментарий от pathfinder

> Я не понял.

Ты и не старался.

И чем это лучше System V semaphore.

Тем, что не надо связываться с SysV IPC и его маразмами.

Просрали токен при падении процесса по segfault и все, система висит?

При падении процесса система закрывает сокет, оставшийся в живых это видит, чистит за собой и завершается. Или просто завершается, неважно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>При падении процесса система закрывает сокет, оставшийся в живых это видит, чистит за собой и завершается. Или просто завершается, неважно.

Так подумаешь. Какие костыли надо городить, чтобы решить простую задачу - синхронизация процессов для доступа к ресурсу?

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

>> При падении процесса система закрывает сокет, оставшийся в живых это видит, чистит за собой и завершается. Или просто завершается, неважно.

Так подумаешь. Какие костыли надо городить, чтобы решить простую задачу - синхронизация процессов для доступа к ресурсу?

Считаешь, что сегмент памяти и семафор будут намного проще?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Считаешь, что сегмент памяти и семафор будут намного проще?

Я считаю, что сделать через flock() очень просто. Можно было бы сделать похожее API для обычных семафоров.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

>> Считаешь, что сегмент памяти и семафор будут намного проще?

Я считаю, что сделать через flock() очень просто.

Ты, конечно, знаешь, что flock не работает на NFS? Что на flock нельзя повесить тайм-аут?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Я как-то обошёлся без этого. Если задачу нельзя решить в общем случае, то это не означает, что её нельзя решить в частном.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

> Я как-то обошёлся без этого.

Как твои клиент и сервер отслеживали зависания друг друга?

Если задачу нельзя решить в общем случае, то это не означает, что её нельзя решить в частном.

Любую разрешимую задачу можно решить несколькими способами. У каждого способа могут быть свои преимущества.

tailgunner ★★★★★
()
Ответ на: комментарий от idle

>> Потому что именованные - это те же сокеты

в смысле?

Не понял, что непонятно. Named pipe aka FIFO - это дуплексный последовательный канал, как и stream-сокет.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Как твои клиент и сервер отслеживали зависания друг друга?

Отслеживанием зависаний занималось другое приложение (которое в свою очередь контролировалось аппаратным watchdog-ом). Если кто-то из процессов повис, то этот процесс прибивался и запускался заново.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

>>>что flock не работает на NFS

А надо?

Вообще, желательно. Потому что частенько практикуется вариант терминального доступа через NFS.

MuZHiK-2 ★★★★
() автор топика
Ответ на: комментарий от pathfinder

>> Как твои клиент и сервер отслеживали зависания друг друга?

Отслеживанием зависаний занималось другое приложение

То есть сами они друг за другом не следили, а был некий мастер-процесс. Как раз то, чего ТС не хочет.

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

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.