LINUX.ORG.RU

Побитовые блокировки с использованием shared-memory

 , locking,


0

1

Я снова хочу невозможного в Perl :(

А именно (речь идёт о Linux, только о Linux, и да, мне абсолютно срать хотелось на переносимость кода в какую-либо иную ОС) :

1) Хочу, чтобы в виртуальное адресное пространство процессов отображалась одна и та же физическая страница

2) Хочу чтобы где-либо на этой странице памяти нашлось место для одного-единственного байта

3) Хочу, чтобы в этот байт можно было делать некий аналог ассемблерного BTS (bit-test-and-set): чтобы атомарным образом содержимое бита сначала сохранялось, а потом тут же устанавливалось

4) Таким образом у меня были бы целых 8 флагов, которые я мог бы использовать для блокировки процессов от повторного запуска: по сохранённому биту я бы определял, была ли блокировка, а если её не было - то я бы изменял значение бита на 1 и последующие инстансы уже не смогли бы сделать те или иные пакости.

Ура?

Подозреваю, что нет.

Мне кажется, и меня это немного пугает, что в Perl5 принято делать блокировки файлами, а гвозди забивать микроскопом, для обладания которым нужно сдать экзамен по вождению марсохода (намекаю на геморрой с правами и путями на любой ФС). Я прав?

P.S. Я пробовал IPC::ShareLite: мало того, что оно вообще не о том (мне НЕ нужно блокировать ресурс в shared memory, у меня самоцель - сам lock), так ещё и работает в на скорую руку состряпаннях тестах - весьма странно (flock вёл себя куда адекватнее).

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 1)

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

DELIRIUM ☆☆☆☆☆
()

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

anonymous
()

Мне кажется, и меня это немного пугает, что в Perl5 принято делать блокировки файлами, а гвозди забивать микроскопом, для обладания которым нужно сдать экзамен по вождению марсохода (намекаю на геморрой с правами и путями на любой ФС). Я прав?

Нет. Используй блокирование файлов или SysV IPC. На сексе с битами ты всё равно ничего не выиграешь - язык у тебя не тот.

tailgunner ★★★★★
()

намекаю на геморрой с правами и путями на любой ФС

Тебе всегда разрешается создать директорию в /tmp и развлекаться там. Есть шанс, что правами на /tmp беда. Но в этом случае и со всей остальной системой беда, так что можешь об этом не думать.

i-rinat ★★★★★
()

Опять извращения с awk на стероидах.

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

На сексе с битами ты всё равно ничего не выиграешь - язык у тебя не тот.

Ммммм

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

Вот вроде бы неплохая вещь, и отлично вписывается в архитектуру, которая итак вся на AnyEvent'е:

http://search.cpan.org/~salva/AnyEvent-Semaphore-0.01/lib/AnyEvent/Semaphore.pm

Но... Мне не нужно ничего ждать, если семафор с size=1 (ИМХО, mutex) «внезапно занят»! Мне нужно просто понять, что «занят» - и пойти себе восвояси.

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

И теперь представьте себе: запустился один такой кусок кода на «регулярной основе». Потом кто-то запустил тот же самый кусок кода из CLI или из «Админки» (на нерегулярной основе). Одно с другим пересеклось, что плохо конечно. И вот тот кусок кода, который из админки толкнули, терпеливо ждёт на семафоре, дожидается... и начинает снова люто терзать память, базу данных (там ещё в самой базе проходит транзакция, так что одновременно в памяти СУБД существуют две копии - «старая», которую она отдаёт клиентам и «новая», радикально изменённая, которая формируется в рамках транзакции), что-то считает... Это при том, что реальная разница в том, ЧТО отправится в кеш между соседними запусками - просто никакая.

В принципе можно наверное исключить повторные запуски именно данного куска кода записью «метки последнего обновления» в кеше (благо, в том же Redis есть операции getset), но... подход уж больно не универсальный и основан просто на том, что «нам нельзя чаще, чем раз в 5 минут, вот нельзя - и всё тут».

Ммм... Есть мысль писать в SCALAR в SharedMemory метку последнего обновления. Тогда и волки будут сыты (можно делать LOCK_NB этого скаляра, и если не удалось залочить - выходить), и овцы целы (я получил лок, посмотрел что там записано, увидел, что времени маловато прошло с прошлого запуска - разлочил и ушёл восвояси ).

Коллеги, как вам последний подход? Или всё-таки писать сие в файлик и делать на нём flock кошернее?

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от tailgunner

LOCK_NB - lock non-blocking.

См. IPC::ShareLite и просто flock. ShareLite дико косячен тем, что он на $resource->lock(LOCK_NB | LOCK_EX) ровным счётом всегда отдаёт 1-цу. Возможно, такой косяк правда только в той версии, что в CentOS 7 из пакетов приезжает.

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

Так нельзя же

Можно. Читай документацию.

$sem->down

Какой down, о чем ты вообще.

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

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

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