Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Циклическая блокировка и семафоры





Циклическая блокировка и семафоры

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

Циклическая блокировка (spinlock) получила свое имя благодаря тому факту, что она выполняется циклически или крутится (spin), ожидая наступления блока. Благодаря такой работе циклической блокировки желательно не вставлять в циклически блокируе­мый код никаких повторных блокировок. Иначе может произойти ступор системы.

Перед применением циклической блокировки структура spin_lock должна быть инициализирована. Это делается с помощью вызова spin_lock_init ():

include/linux/spinlock.h

63 #define spin_lock_init(x) \

64 do { \

65 (x)-> magic = SPINLOCK_MAGIC; \

66 (x)-> lock = 0; \

67 (x)-> babble = 5; \

68 (x)-> module = _ FILE_; \

69 (x)-> owner = NULL; \

70 (x)-> oline = 0; \

71 } while (0)

Этот блок кода устанавливает spin_lock в «разблокированное» состояние или в 0 в строке 66 и инициализирует другие переменные структуры. Здесь мы коснемся перемен­ной (х) -> 1оск.

После инициализации spin_lock ее можно получить с помощью spin_lock() или spin_lock_irqsave (). Функция spin_lock_irqsave () отключает прерыва­ния перед блокировкой, a spin_lock () - нет. Если вы используете spin_lock (), про­цесс может быть прерван в заблокированном разделе кода.

Для освобождения spin_lock после выполнения критической секции кода вам нужно вызвать spin_unlock() или spin_unlock_irqrestore(); spin_unlock_irqrestore() восстанавливает состояние регистров прерывания до уровня, в котором они были до вызова spin_lock_irq ().

Давайте рассмотрим вызовы spin_lock_irqsave () и spin_unlock_ irqre-store().

include/linux/spinlock.h

258 #define spin_lock_irqsave(lock, flags) \

259 do { \

260 local_irq_save(flags); \



Глава 7 • Планировщик и синхронизация ядра


261 preempt_disable(); \

262 _raw_spin_lock_flags(lock, flags); \

263 } while (0)

321 #define spin_unlock_irqrestore(lock/ flags) \

322 do { \

 

323 _raw_spin_unlock(lock); \

324 local_irq_restore(flags); \

325 preempt_enable(); \

326 } while (0)

Обратите внимание, как во время блокировки отключается приоритетное прерыва­ние обслуживания. После этого можно быть уверенным, что операции в критической сек­ции не будут прерваны. Флаг IRQ сохраняется в строке 260 и восстанавливается в строке 324.

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

Семафоры отличаются от циклической блокировки тем, что при возникновении кон­курентного обращения к ресурсу задача засыпает вместо того, чтобы быть в бесконечном ожидании. Достоинством семафора является безопасность блокировки; они безопасны при выполнении на SMP и при возникновении прерываний.

include/asm-i3 8 б/semaphore.h

44 struct semaphore {

45 atomic_t count;

46 int sleepers;

47 wait_queue_head_t wait;

48 #ifdef WAITQUEUE_DEBUG

49 long _ magic;

50 #endif

51 };

include/asm-ppc/semaphore.h

24 struct semaphore {

25 /*

2 6 * Обратите внимание, что отрицательное значение счетчика

27 * эквивалентно 0, а также дополнительно означает, что процесс

28 * (процессы) должен спать или ожидать.

29 */

3 0 atomic_t count;


Системные часы: прошедшее время и таймеры



31 wait_queue_head_t wait;

32 #ifdef WAITQUEUE_DEBUG

33 long __ magic;

3 4 #endif

35 };

Реализации на обеих архитектурах предоставляет указатель на wait_queue и счетчик. Счетчик хранит количество процессов, которые может хранить семафор в каж­дый из промежутков времени. Применяя семафор, мы можем иметь несколько процессов, одновременно вошедших в код критической секции. Если счетчик инициализирован в 1, только один процесс может войти в код критической секции; семафор со счетчиком, рав­ным 1, называется мьютексом (mutex).

Семафоры инициализируются с помощью sema_init О, а их блокировка и разбло­кирование производятся с помощью вызовов down () и up () соответственно. Помимо этого, существует down_interruptible (), которая возвращает 0, если семафор по­лучен, и EINTR, если процесс был прерван при блокировке.

Когда процесс вызывает down () или down_interrruptible (), поле счетчика в семафоре уменьшается. Если значение поля меньше 0, вызывающий down () процесс бло­кируется и добавляется в wait_queue семафора. Если поле больше либо равно 0, про­цесс продолжает свою работу.

После выполнения кода критической секции процесс должен вызвать up () для со­общения семафору о завершении работы с критической секцией. С помощью вызова up () процесс увеличивает значение поля count в семафоре и, если счетчик больше или равен О, пробуждает процесс, ожидающий в wait_queue семафора.

Системные часы: прошедшее время и таймеры

В целях планирования ядро использует системные часы для определения того, как долго выполняется задача. Мы уже рассматривали системные часы в гл. 5 и использовали их в качестве примера для обсуждения прерываний. Здесь мы рассмотрим часы реального времени, их применение и реализацию, но для начала давайте определимся с основными понятиями часов.

Часы - это периодические сигналы, возникающие в процессоре, позволяющие ему обрабатывать кванты времени. Процессор в соответствии с сигналом часов узнает, когда ему нужно выполнить следующую операцию, такую, как сложение двух целых чисел или извлечение значения из памяти. Скорость этого сигнала часов (1.4 ГГц, 2 ГГц и т. д.) исторически применяется для сравнения скорости процессора системы на рынке элек­троники.

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



Глава 7 • Планировщик и синхронизация ядра


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

Часы реального времени: что это такое

В Linux интерфейс к таймеру настенных часов предоставляется через функцию ioctl () драйвера устройства /dev/rtc. Устройство этого драйвера называется Real Time Clock (RTC)1. RTC2 предоставляет функцию для работы со 114-битовым значением в NVRAM. На входе этого устройства установлен осциллятор с частотой 32768 КГц, под­соединенный к резервной батарее. Некоторые дискретные модели RTC имеют встроен­ные осциллятор и батарею, тогда как другие RTC встраиваются прямо в контроллер периферийной шины (например, южный мост) чипсета процессора. RTC возвращает не только время суток, но, помимо прочего, является и программируемым таймером, имеющим возможность посылать системные прерывания. Частота прерываний варьиру­ется от 2 до 8192 Гц. Также RTC может посылать прерывания ежедневно, наподобие бу­дильника. Далее мы рассмотрим код RTC.

/include/linux/rtc.h /*

* ioctl вызывает приоритетное прерывание обслуживания для /dev/rtc

* interface, если включен любой из RTC-драйверов. */

 

70 #define RTC_AIE_ON _IO('p', 0x01) /* Включение прерывания звонка */

71 #define RTC_AIE__OFF _IO('р', 0x02) /*... отключение */

/* Включение прерывания обновления */

72 #define RTC_UIE_ON _IO(•p■, 0x03)

73 #define RTC_UIE_OFF _IO('p', 0x04) /*... отключение */

/* Включение периодического прерывания */

74 #define RTC_PIE__ON JOCp', 0x05)

75 #define RTC_PIE_OFF „ЮС'р', 0x06) /*... отключение */

/* Включение сторожевого прерывания */

76 #define RTC_WIE_ON „ЮСр', OxOf)

77 #define RTC_WIE_OFF _IO('p', 0x10) /*... отключение */

1 Часы реального времени. Примеч. пер.

2 Производится несколькими поставщиками. Наиболее распространенным является вариант тс146818 от
Motorola. (Данный RTC больше не производится, и его место занял Dallas DS12885 или его эквиваленты.)


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-03-25; Просмотров: 1028; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.022 с.)
Главная | Случайная страница | Обратная связь