Блокировка файлов против семафоров

Просто из любопытства, какой предпочтительный способ достижения синхронизации между процессами в Linux? Семейство системных вызовов sem * (2) , похоже, имеет очень неуклюжий и устаревший интерфейс, в то время как есть три способа блокировки файлов - fcntl () , flock ( ) и lockf () .

Каковы внутренние различия (если таковые имеются) и как бы вы обосновали использование каждого из них?

8
задан Blagovest Buyukliev 25 August 2010 в 18:05
поделиться

4 ответа

Ни то, ни другое. Все актуальные версии pthread _ * (например, phtread_mutex_t ) позволяют размещать переменные в общих сегментах, которые создаются с помощью shm_open . Вам просто нужно добавить дополнительный параметр в вызовы init.

Не используйте семафоры ( sem_t ), если вам не нужно, они слишком низкоуровневые и прерываются вводом-выводом и т. Д.

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

9
ответ дан 5 December 2019 в 08:50
поделиться

Различные реализации блокировок и семафоров появились в разных системах. В System V Unix у вас было semget/semop, POSIX определил другую реализацию с sem_init, sem_wait и sem_post. ]. А flock возник в 4.2BSD, насколько мне удалось выяснить.

Поскольку все они приобрели определенное значение, Linux теперь поддерживает их все, чтобы упростить перенос. Кроме того, flock является мьютексом (заблокированным или разблокированным), но функции sem* (и SysV, и POSIX) являются семафорами: они позволяют приложению предоставлять доступ нескольким параллельным процессам, например вы можете разрешить доступ к ресурсу 4 процессам одновременно с семафорами. Вы можете реализовать мьютекс с семафорами, но не наоборот. Я помню, что в прекрасном "Advanced UNIX Programming" Марка Дж. Рочкинда он продемонстрировал, как передавать данные между процессами через семафоры (очень неэффективно, он сделал это только для того, чтобы доказать, что это возможно). Но я не мог найти ничего достоверного об эффективности.

Думаю, это больше похоже на «Используй, что хочешь».

3
ответ дан 5 December 2019 в 08:50
поделиться

Потенциально существенным отличием может быть справедливость распределения ресурсов. Я не знаю подробностей реализации семейства semget/semop, но подозреваю, что оно обычно реализуется как «традиционный» семафор в том, что касается планирования. Как правило, я считаю, что освобожденные потоки обрабатываются по принципу FIFO (первым освобождается первый, ожидающий семафора). Я не думаю, что это произойдет с блокировкой файлов, поскольку я подозреваю (опять же просто предполагаю), что обработка не выполняется на уровне ядра.

У меня был существующий код для тестирования семафоров для целей IPC, поэтому я сравнил две ситуации (одна с использованием semop и одна с использованием lockf).Я сделал тест бедняка и просто побежал к экземплярам приложения. Общий семафор использовался для синхронизации запуска. При выполнении теста semop оба процесса почти синхронно выполнили 3 миллиона циклов. С другой стороны, петля lockf была не столь справедливой. Один процесс обычно заканчивался, в то время как другой завершал только половину циклов.

Цикл теста semop выглядел следующим образом. Функции semwait и semsignal являются просто оболочками для вызовов semop.

   ct = myclock();
   for ( i = 0; i < loops; i++ )
      {
      ret = semwait( "test", semid, 0 );
      if ( ret < 0 ) { perror( "semwait" ); break; }

      if (( i & 0x7f ) == 0x7f )
         printf( "\r%d%%", (int)(i * 100.0 / loops ));

      ret = semsignal( semid, 0 );
      if ( ret < 0 ) { perror( "semsignal" ); break; }
      }
   printf( "\nsemop time: %d ms\n", myclock() - ct );

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

При безальтернативной работе (один процесс получает и снимает блокировки) версия semop работала быстрее. На 1 миллион итераций ушло около 2 секунд, в то время как для версии lockf потребовалось около 3 секунд.

Это было запущено на следующей версии:

[]$ uname -r
2.6.11-1.1369_FC4smp
2
ответ дан 5 December 2019 в 08:50
поделиться

Вы страдаете от множества вариантов выбора из богатой истории, как заметил DarkDust. Что бы это ни стоило, мое дерево решений выглядит примерно так:

Используйте мьютексы, когда только один процесс/поток может иметь доступ одновременно.

Используйте семафоры, когда два или более (но, тем не менее, конечных) процессов/потоков могут использовать ресурс.

Используйте семафоры POSIX, если вам действительно не нужны семафоры SYSV, например. UNDO, PID последней операции и т. д.

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

5
ответ дан 5 December 2019 в 08:50
поделиться
Другие вопросы по тегам:

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