Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Циклическая блокировка и семафоры
Циклическая блокировка и семафоры Когда два или более процесса требуют специального доступа к разделяемому ресурсу, они вынуждены устроить состязание за управление данным блоком кода. Базовой формой блокировки в 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 от Популярное: |
Последнее изменение этой страницы: 2016-03-25; Просмотров: 1028; Нарушение авторского права страницы