Роберт Лав - Разработка ядра Linux
- Название:Разработка ядра Linux
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2006
- Город:Москва
- ISBN:5-8459-1085-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Роберт Лав - Разработка ядра Linux краткое содержание
В книге детально рассмотрены основные подсистемы и функции ядер Linux серии 2.6, включая особенности построения, реализации и соответствующие программны интерфейсы. Рассмотренные вопросы включают: планирование выполнения процессов, управление временем и таймеры ядра, интерфейс системных вызовов, особенности адресации и управления памятью, страничный кэш, подсистему VFS, механизмы синхронизации, проблемы переносимости и особенности отладки. Автор книги является разработчиком основных подсистем ядра Linux. Ядро рассматривается как с теоретической, так и с прикладной точек зрения, что может привлечь читателей различными интересами и потребностями.
Книга может быть рекомендована как начинающим, так и опытным разработчикам программного обеспечения, а также в качестве дополнительных учебных материалов.
Разработка ядра Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Последний метод используется для инкремента значения счетчика. Если очередь ожидания семафора не пуста, то одно из заданий этой очереди возвращается к выполнению и захватывает семафор.
Создание и инициализация семафоров
Реализация семафоров зависит от аппаратной платформы и определена в файле . Структура struct semaphore
представляет объекты типа семафор. Статическое определение семафоров выполняется следующим образом.
static DECLARE_SEMAPHORE_GENERIC(name, count);
где name
— имя переменной семафора, a count
— счетчик семафора. Более короткая запись для создания взаимоисключающей блокировки (mutex), которая используются наиболее часто, имеет следующий вид.
static DECLARE_MUTEX(name);
где name
— это снова имя переменной типа семафор. Чаще всего семафоры создаются динамически, как часть больших структур данных. В таком случае для инициализации семафора, который создается динамически и на который есть только непрямая ссылка через указатель, необходимо использовать функцию
sema_init(sem, count);
где sem
— это указатель, a count
— счетчик использования семафора. Аналогично для инициализации динамически создаваемой взаимоисключающей блокировки можно использовать функцию
init_MUTEX(sem);
Неизвестно, почему слово "mutex" в имени функции init_MUTEX()
выделено большими буквами и почему слово "init" идет перед ним, в то время как имя функции sema_init()
таких особенностей не имеет. Тем не менее ясно, что это выглядит не логично, и я приношу свои извинения за это несоответствие. Надеюсь, что после прочтения главы 7 ни у кого уже не будет вызывать удивление то, какие имена придумывают символам ядра.
Использование семафоров
Функция down_interruptible()
выполняет попытку захватить данный семафор. Если эта попытка неудачна, то задание переводится в состояние ожидания с флагом TASK_INTERRUPTIBLE
. Из материала главы 3 следует вспомнить, что такое состояние процесса означает, что задание может быть возвращено к выполнению с помощью сигнала и что такая возможность обычно очень ценная. Если сигнал приходит в тот момент, когда задание ожидает на освобождение семафора, то задание возвращается к выполнению, а функция down_interruptible()
возвращает значение -EINTR
. Альтернативой рассмотренной функции выступает функция down()
, которая переводит задание в состояние ожидания с флагом TASK_UNINTERRUPTIBLE
. В большинстве случаев это нежелательно, так как процесс, который ожидает на освобождение семафора, не будет отвечать на сигналы. Поэтому функция down_interruptible()
используется значительно более широко, чем функция down()
. Да, имена этих функций, конечно, далеки от идеала.
Функция down_trylock()
используется для неблокирующего захвата указанного семафора. Если семафор уже захвачен, то функция немедленно возвращает ненулевое значение. В случае успеха по захвату блокировки возвращается нулевое значение и захватывается блокировка.
Для освобождения захваченного семафора необходимо вызвать функцию up()
. Рассмотрим следующий пример.
/* объявление и описание семафора с именем mr_sem и
первоначальным значением счетчика, равным 1 */
static DECLARE_MUTEX(mr_sem);
...
if (down_interruptible(&mr_sem))
/* получен сигнал и семафор не захвачен */
/* критический участок ... */
/* освободить семафор */
up(&mr_sem);
Полный список функций работы с семафорами приведен в табл. 9.5.
Таблица 9.5. Список функций работы с семафорами
Функция | Описание |
---|---|
sema_init(struct semaphore*, int) |
Инициализация динамически созданного семафора и установка для него указанного значения счетчика использования |
init_MUTEX(struct semaphore*) |
Инициализация динамически созданного семафора и установка его счетчика использования в значение 1 |
init_MUTEX_LOCKED (struct semaphore*) |
Инициализация динамически созданного семафора и установка его счетчика использования в значение 0 (т.е. семафор изначально заблокирован) |
down_interruptible(struct semaphore *) |
Выполнить попытку захватить семафор и перейти в прерываемое состояние ожидания, если семафор находится в состоянии конфликта при захвате (contended) |
down(struct semaphore*) |
Выполнить попытку захватить семафор и перейти в непрерываемое состояние ожидания, если семафор находится в состоянии конфликта при захвате (contended) |
down_trylock(struct semaphore*) |
Выполнить попытку захватить семафор и немедленно возвратить ненулевое значение, если семафор находится в состоянии конфликта при захвате (contended) |
up(struct semaphore*) |
Освободить указанный семафор и возвратить к выполнению ожидающее задание, если такое есть |
Семафоры чтения-записи
Семафоры, так же как и спин-блокировки, могут быть типа чтения-записи. Ситуации, в которых предпочтительнее использовать семафоры чтения-записи такие же как и в случае использования спин-блокировок чтения-записи.
Семафоры чтения-записи представляются с помощью структуры struct rw_semaphore
, которая определена в файле . Статически определенный семафор чтения-записи может быть создан с помощью функции
static DECLARE_RWSEM(name);
где name
— это имя нового семафора.
Семафоры чтения-записи, которые создаются динамически, могут быть инициализированы с помощью следующей функции.
init_rwsem(struct rw_semaphore *sem);
Все семафоры чтения-записи являются взаимоисключающими (mutex), т.е. их счетчик использования равен единице. Любое количество потоков чтения может одновременно удерживать блокировку чтения, если при этом нет ни одного потока записи. И наоборот, только один поток записи может удерживать блокировку, захваченную на запись, если нет ни одного потока чтения. Все семафоры чтения-записи используют непрерываемое состояние ожидания, поэтому существует только одна версия функции down().
Рассмотрим следующий пример.
static DECLARE_RWSEM(mr_rwsem);
/* попытка захватить семафор для чтения */
down_read(&mr_rwsem);
/* критический участок (только чтение) ... */
/* освобождаем семафор */
up_read(&mr_rwsem);
/* ... * /
/* попытка захватить семафор на запись */
down_write(&mr_rwsem);
/* освобождаем семафор */
/* критический участок (чтение и запись) ... */
up write(&mr_rwsem);
Для семафоров есть реализации функций down_read_trylock()
и down_write_trylock()
. Каждая из них принимает один параметр — указатель на семафор чтения-записи. Обе функции возвращают ненулевое значение, если блокировка захвачена успешно, и нуль, если блокировка находится в состоянии конфликта. Следует быть внимательными — поведение этих функций противоположно поведению аналогичных функций для обычных семафоров, причем без всякой на то причины!
Интервал:
Закладка: