Что лучшее ядро Linux блокирует механизм для определенного сценария

Я должен решить проблему блокировки для этого сценария:

  1. Много система ЦП.
  2. Все использование ЦП общее (программное обеспечение) ресурс.
  3. Доступ только для чтения к ресурсу очень распространен. (Обработка входящих сетевых пакетов)
  4. Доступ для записи является намного менее частым. (В значительной степени только изменения конфигурации).

В настоящее время я использую read_lock_bh, write_lock_bh (спин-блокировки) механизм. Проблема - это, чем больше ЦП, тем больше я получаю мягкие тупики в контексте устройства записи.

Я прочитал главу параллелизма в этой книге, Но не мог вполне понять, получат ли средство чтения или устройство записи приоритет при использовании спин-блокировок.

Таким образом, вопросы:

  1. Механизм спин-блокировки Linux уделяет reader/writer/none первостепенное значение их?
  2. Существует ли лучший механизм, который я могу использовать для предотвращения тех мягких тупиков в моем сценарии или возможно способа для меня уделить первостепенное значение устройству записи каждый раз, когда он пытается получить блокировку при использовании моего текущего решения?

Спасибо, Nir

6
задан red0ct 4 December 2019 в 11:06
поделиться

3 ответа

Вот прямая цитата из Essential Linux Device Drivers , которая может быть тем, что вы ищете. Кажется, часть, имеющая отношение к RCU в конце, может быть тем, что вас интересует.

Блокировки чтения-записи

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

rwlock_t myrwlock = RW_LOCK_UNLOCKED;

read_lock(&myrwlock);             /* Acquire reader lock */
/* ... Critical Region ... */
read_unlock(&myrwlock);           /* Release lock */

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

rwlock_t myrwlock = RW_LOCK_UNLOCKED;

write_lock(&myrwlock);            /* Acquire writer lock */
/* ... Critical Region ... */
write_unlock(&myrwlock); /* Release lock */

Посмотрите на код маршрутизации IPX, представленный в net / ipx / ipx_route.c , чтобы увидеть реальный пример спин-блокировки чтения-записи. А Блокировка чтения-записи, называемая ipx_routes_lock , защищает таблицу маршрутизации IPX от одновременного доступа. Потоки которым необходимо найти таблицу маршрутизации для пересылки пакетов, запрашивающих блокировки считывателя. Темы, которые нужно добавить или удалить записи из таблицы маршрутизации получить блокировки писателя. Это улучшает производительность, потому что обычно гораздо больше экземпляров поиска в таблице маршрутизации, чем обновления таблицы маршрутизации.

Как и обычные спин-блокировки, блокировки чтения-записи также имеют соответствующие варианты irq, а именно, read_lock_irqsave () , read_lock_irqrestore () , write_lock_irqsave () и write_lock_irqrestore () . Семантика этих функции аналогичны функциям обычных спин-блокировок.

Блокировки последовательностей или seqlocks, представленные в ядре 2.6, являются блокировками чтения-записи, где писатели предпочитают читатели. Это полезно, если операций записи для переменной намного больше, чем операций чтения. Примером может служить jiffies_64 , обсуждаемая ранее в этой главе. Потоки писателя не ждут читателей, которые могут быть внутри критический раздел. Из-за этого читательские потоки могут обнаружить, что их вход в критическую секцию не удался. и может потребоваться повторная попытка:

u64 get_jiffies_64(void) /* Defined in kernel/time.c */
{
   unsigned long seq;
   u64 ret;
   do {
      seq = read_seqbegin(&xtime_lock);
      ret = jiffies_64;
   } while (read_seqretry(&xtime_lock, seq));
   return ret;
}

Устройства записи защищают критические области с помощью write_seqlock () и write_sequnlock () .

В ядре 2.6 появился еще один механизм, называемый Read-Copy Обновление (RCU) , , которое дает улучшенные производительность, когда читателей намного больше, чем писателей . Основная идея заключается в том, что потоки чтения могут выполняться без блокировка. Писатели более сложные. Они выполняют операции обновления копии структуры данных и замените указатель, который видят читатели. Исходная копия сохраняется до следующего переключения контекста на всех ЦП на обеспечить завершение всех текущих операций чтения. Имейте в виду, что использование RCU более сложное, чем использование примитивы, обсуждаемые до сих пор, и должны использоваться только в том случае, если вы уверены, что это правильный инструмент для работы. Данные RCU структуры и интерфейсные функции определены в include / linux / rcupdate.h . В Documentation / RCU / * .

Пример использования RCU см. В fs / dcache.c . В Linux каждый файл связан с записью каталога информация (хранящаяся в структуре, называемой dentry), информация метаданных (хранящаяся в индексном узле) и фактические данные (хранится в блоках данных). Каждый раз, когда вы работаете с файлом, компоненты пути к файлу анализируются, и получаются соответствующие дентри. Дентри хранятся в кэше в структуре данных, называемой dcache, чтобы ускорить будущие операции. В любой момент количество поисков dcache намного больше, чем обновлений dcache, поэтому ссылки на dcache защищены примитивами RCU.

6
ответ дан 10 December 2019 в 02:52
поделиться

Разве это не тот случай использования, для обработки которого предназначен RCU? См. http://lwn.net/Articles/262464/ , где подробно описано его использование.

3
ответ дан 10 December 2019 в 02:52
поделиться

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

0
ответ дан 10 December 2019 в 02:52
поделиться
Другие вопросы по тегам:

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