Чтение онлайн

на главную

Жанры

Разработка ядра Linux
Шрифт:
Функция Описание
lock_kernel
Захватить блокировку BKL
unlock_kernel
Освободить блокировку BKL
kernel_locked
Возвратить ненулевое значение, если блокировка захвачена, и нуль- в противном случае

Одна из самых главных проблем, связанных с большой блокировкой ядра, — как определить, что защищается с помощью данной блокировки. Часто блокировка BKL ассоциируется с кодом (например,

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

Секвентные блокировки

Секвентная блокировка (seq lock) — это новый тип блокировки, который появился в ядрах серии 2.6. Эти блокировки предоставляют очень простой механизм чтения и записи совместно используемых данных. Работа таких блокировок основана на счетчике последовательности событий. Перед записью рассматриваемых данных захватывается спин-блокировка, и значение счетчика увеличивается на единицу. После записи данных значение счетчика снова увеличивается на единицу, и спин-блокировка освобождается, давая возможность записи другим потокам. Перед чтением и после чтения данных проверяется значение счетчика. Если два полученных значения одинаковы, то во время чтения данных новый акт записи не начинался, Если к тому же оба эти значения четные, то к моменту начала чтения акт записи был закончен (при захвате блокировки на запись значение счетчика становится нечетным, а перед освобождением — снова четным, так как изначальное значение счетчика равно нулю).

Определение секвентной блокировки можно записать следующим образом.

seqlock_t mr_seq_lock = SEQLOCK_UNLOCKED;

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

write_seqlock(&mr_seq_lock);

/* блокировка захвачена на запись ... */

write_sequnlock(&mr_seq_lock);

Это выглядит, как работа с обычной спин-блокировкой. Необычность появляется в коде чтения, который несколько отличается от ранее рассмотренных.

unsigned long seq;

do {

 seq = read_seqbegin(&mr_seq_lock);

 /* здесь нужно читать данные ... */

} while (read_seqretry(&mr_seq_lock, seq));

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

Средства запрещения преемптивности

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

качестве маркеров, чтобы отмечать участки "непреемптивности". Если спин-блокировка захвачена, то ядро является невытесняемым. Так как проблемы, связанные с параллелизмом, в случае SMP и преемптивного ядра одинаковы, то, если ядро уже является безопасным для SMP-обработки, такое простое дополнение позволяет также сделать ядро безопасным и при вытеснении.

Будем надеяться, что это действительно так. На самом деле возникают некоторые ситуации, в которых нет необходимости использовать спин-блокировки, но нужно запрещать преемптивность ядра. Наиболее часто ситуация такого рода возникает из-за данных, привязанных к определенным процессорам (per-processor data). Если используются данные, уникальные для каждого процессора, то может быть необязательным защищать их с помощью спин-блокировок, потому что только один процессор может получать доступ к этим данным. Если никакая спин-блокировка не захвачена и ядро является преемптивным, то появляется возможность доступа к тем же переменным для вновь запланированного задания, как показано в следующем примере.

задание А манипулирует переменной foo

задание А вытесняется

задание В планируется на выполнение

задание В манипулирует переменной foo

задание В завершается

задание А планируется на выполнение

задание А манипулирует переменной foo

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

Для решения указанной проблемы преемптивность ядра можно запретить с помощью функции

preempt_disable
. Этот вызов может быть вложенным, т.е. функцию можно вызывать много раз подряд. Для каждого такого вызова требуется соответствующий вызов функции
preempt_enable
. Последний вызов функции
preempt_enable
разрешает преемптивность, как показано в следующем примере.

preempt_disable;

/* преемптивность запрещена ... */

preempt_enable;

Счетчик преемптивности текущего процесса содержит значение, равное количеству захваченных этим процессом блокировок плюс количество вызовов функции

preempt_disable
. Если значение этого счетчика равно нулю, то ядро является вытесняемым. Если значение этого счетчика больше или равно единице, то ядро не вытесняемое. Данный счетчик невероятно полезен для отладки атомарных операций совместно с переходами в состояние ожидания. Функция
preempt_count
возвращает значение данного счетчика. В табл. 9.9 показан полный список функций управления преемптивностью.

Таблица 9.9. Функции управления преемптивностью ядра

Функция Описание
preempt_disable
Запретить вытеснение кода ядра
preempt_enable
Разрешить вытеснение кода ядра
preempt_enable_no_resched
Разрешить вытеснение кода ядра, но не перепланировать выполнение процесса
preempt count
Возвратить значение счетчика преемптивности
Поделиться:
Популярные книги

Ученичество. Книга 1

Понарошку Евгений
1. Государственный маг
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ученичество. Книга 1

Матабар III

Клеванский Кирилл Сергеевич
3. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар III

Кодекс Охотника. Книга XXIII

Винокуров Юрий
23. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXIII

Вопреки судьбе, или В другой мир за счастьем

Цвик Катерина Александровна
Любовные романы:
любовно-фантастические романы
6.46
рейтинг книги
Вопреки судьбе, или В другой мир за счастьем

Идеальный мир для Лекаря 23

Сапфир Олег
23. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 23

Довлатов. Сонный лекарь

Голд Джон
1. Не вывожу
Фантастика:
альтернативная история
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь

Мама из другого мира. Дела семейные и не только

Рыжая Ехидна
4. Королевский приют имени графа Тадеуса Оберона
Любовные романы:
любовно-фантастические романы
9.34
рейтинг книги
Мама из другого мира. Дела семейные и не только

Великий род

Сай Ярослав
3. Медорфенов
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Великий род

Проданная Истинная. Месть по-драконьи

Белова Екатерина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Проданная Истинная. Месть по-драконьи

Треск штанов

Ланцов Михаил Алексеевич
6. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Треск штанов

Лучший из худших

Дашко Дмитрий
1. Лучший из худших
Фантастика:
фэнтези
попаданцы
5.25
рейтинг книги
Лучший из худших

На границе империй. Том 8. Часть 2

INDIGO
13. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 8. Часть 2

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Сила рода. Том 3

Вяч Павел
2. Претендент
Фантастика:
фэнтези
боевая фантастика
6.17
рейтинг книги
Сила рода. Том 3