Ю. Вахалия - UNIX изнутри (2003) (1114670), страница 25
Текст из файла (страница 25)
Если объект уже заблокирован, библиотека приостановит выполнение нити, связав ее с очередью блокированных нитей, и передаст управление следующей нити. Современные системы 1ЛЧ1Х поддерживают механизмы асинхронного ввода-вывода, позволяющие процессам выполнять ввод-вывод без блокирования. Например, в системе Б'сто для любого устройства, работа с которым может быть организована через 5ТЙЕАМ5, предлагается 1осс!-команда 10 5ЕТ516 (технология 5ТКЕАМ5 описана в главе 17). Последующие' операции ьуп1е или геао с потоком просто встают в очередь операций и возвращают значения без блокирования.
Когда ввод-вывод завершится, процесс будет проинформирован об этом при помощи сигнала 516Р00.. Асинхронный ввод-вывод является весьма полезным средством, так как позволяет процессу выполнять другие задачи во время ожидания завершения ввода-вывода. Но, с другой стороны, его реализация ведет к усложнению модели выполнения программы.
Одним из удачных решений является организация возможности асинхронной работы на уровне операционной системы, предоставляющая для выполнения программы синхронную среду. Нитевая библиотека обеспечивает такой подход посредством предоставления синхронного интерфейса, использующего асинхронный внутренний механизм. Каждый запрос является синхронным по отношению к делающей его нити, которая блокируется в ожидании окончания операции ввода-вывода. Однако при этом процесс будет продолжать свое выполнение, так как библиотека внутри себя преобразует запрос в виде асинхронной операции и назначит на выполнение следующую по очереди прикладную нить. После завершения ввода-вывода библиотека снова поместит в расписание выполнения приостановленную нить.
Использование прикладных нитей имеет несколько преимуществ. Они предоставляют более естественный способ программирования многих приложе- ' То есть сделанные после вышеуказанного вызова шснм — Прим. ред. 110 Глава 3. Нити и легковесные процессы Таблица 3.1. Длительность операций, производимых прикладными нитями, 'ьттР и процессами (на 8РАПСз!акоп 2) Создание, мкс Синхронизация с использованием семафоров, мкс Пользовательская нить 52 66 390 200 350 1700 Процесс Однако прикладные нити обладают и рядом ограничений, большинство из которых является следствием полного разделения информации между ядром и иитевой библиотекой.
Так как ядро системы ничего ие знает о прикладных нитях, оио ие может использовать свои механизмы для их защиты друг от друга. Каждый процесс имеет свое адресное пространство, защищаемое ядром от несанкционированного доступа других процессов. Прикладные нити лишены такой возможности, так как функционируют в общем адресном пространстве процесса. Нитевая библиотека должна обеспечивать средства синхронизации, необходимые для совместной работы нитей. иий, например таких, как оконные системы.
Прикладные нити также обеспечивают синхронный подход к выполнению программы, поскольку все сложные асинхронные операции скрыты в недрах иитевых библиотек. Одно только это делает применение прикладных нитей весьма привлекательным, даже в системах, ие обладающих поддержкой нитей иа уровне ядра. Система может предлагать разработчику несколько различных иитевых библиотек, каждая из которых оптимизирована для различных классов приложений. Важнейшим преимуществом прикладных нитей является их производительность.
Эти нити являются легковесными и ие потребляют ресурсов ядра, кроме связанных с г.ЮР. В основе производительности работы прикладных нитей лежит реализация всей их функциональности иа прикладном уровне без применения системных вызовов. Такой подход не требует дополнительной обработки системных прерываний и перемещения параметров и данных через границы защиты. Одним из важных параметров нити является критический размер нити ~4~, который показывает тот объем работы, который нить должна выполнить для того, чтобы оправдать свое существование в качестве отдельной сущности.
Этот размер зависит от затрат иа создание и использование нити. Для прикладных нитей критический размер составляет порядка нескольких сотен инструкций, количество которых может быть сокращено менее чем иа сотню, в зависимости от используемого компилятора.
Прикладные нити требуют значительно меньшего количества времени для создания, уничтожения и синхронизации. Таблица 3.1 показывает длительность различных операций, производимых процессами, ЕЮР и прикладными нитями иа машине 5РЛКСзгас1оп 2 [21]. 3.2. Основные типы нитей 11 1 Использование модели разделенного планирования может стать причиной возникновения множества других проблем. Нитевая библиотека занимается планированием выполнения прикладных нитей, ядро планирует выполнение процессов или легковесных процессов, в которых эти нити функционируют, и в итоге никто из них не знает о действиях друг друга. Например, ядро может вытеснить 1.%'Р, чья прикладная нить находится в области, защищаемой циклической блокировкой (зр1п 1оск), удерживая эту блокировку активной.
Если иная прикладная нить иного ИЪ'Р попытается снять эту блокировку, то она перейдет в цикл активного ожидания до тех пор, пока удерживающая циклическую блокировку нить не получит возможности работать снова. С другой стороны, так как ядро системы не знает относительных приоритетов прикладных нитей, оно вполне может вытеснить один легковесный процесс с выполняемой внутри нитью высокого приоритета, поставив на выполнение другой 1Л)Р, нить которого имеет более низкий приоритет.
Механизмы синхронизации, организованные на прикладном уровне, могут в некоторых случаях работать некорректно. Большинство приложений создаются с предположением, что все работающие нити периодически попадают в очередь на выполнение. Это действительно так, если каждая нить находится в отдельном 1.%'Р, но предположение может не выполняться в тех случаях, когда некоторое количество прикладных нитей мультиплексируется в меньшем количестве 1.ИР. Так как 1.ЮР может блокироваться в ядре, когда его прикладная нить делает блокирующий системный вызов, такой ЕЪ'Р процесса умеет останавливать свою работу даже тогда, когда остаются работающие нити, а в системе — доступные процессоры.
Разрешить эту проблему можно при помощи использования механизмов асинхронного ввода-вывода. И наконец, следует упомянуть о том, что без явной поддержки на уровне ядра прикладные нити в состоянии увеличить одновременность выполнения, но не могут увеличить параллельность. Даже на многопроцессорных системах прикладные нити, разделяющие между собой один легковесный процесс, не могут выполняться параллельно. В этом разделе были описаны три основных, наиболее используемых типа нитей.
Нити ядра являются объектами самого нижнего уровня и невидимы для приложений. Легковесные процессы — это нити, видимые на прикладном уровне, но распознаваемые при этом ядром и опирающиеся на нити ядра. Прикладные нити представляют собой объекты высокого уровня, не видимые ядром. Они могут использовать легковесные процессы (если таковые поддерживаются системой) или реализовываться в обычных процессах ПЧ1Х без специальной поддержки ядром.
И прикладные нити, и ЫЪ'Р имеют некоторые существенные недостатки, ограничивающие их область применения. В разделе 3.5 вы увидите описание новой фундаментальной структуры, основанной на активациях планировщика, которая показывает многие из этих проблем. Однако сначала мы затронем некоторые вопросы, касающиеся прикладных нитей и 1ЛЧР, подробнее. 112 Глава 3. Нити и легковесные процессы 3.3. Легковесные процессы: основные проблемы Сушествует несколько различных факторов, влияющих на устройство легковесных процессов. В первую очередь, необходимо сохранять семантику, принятую в системах 111ч1Х, по крайней мере, для однонитевых вариантов. Это означает, что процесс, содержащий единственный 1,ЪЪ'Р, должен функционировать как традиционный процесс 1)Ы1Х, (Стоит снова упомянуть, что под 1.т1ГР мы понимаем прикладные нити, поддерживаемые ядром, а не легковесные процессы системы БппО5 4.0, которые являются объектами полностью прикладного уровня,) Сушествуют различные области, где концепцию 111ч1Х нельзя легко перенести на многонитевую систему.
Следуюшие разделы посвящены описанию возникающих проблем и способам их решения. 3.3.1. Семантика вызова 1огК Системные вызовы в многонитевых средах принимают несколько необычные значения. Многие вызовы, имеющие отношение к созданию процессов, манипуляциям над адресным пространством или действиям над ресурсами процесса (такими как открытые файлы), должны быть переписаны заново.
Есть две важные рекомендации. Во-первых, системный вызов должен придерживаться традиционной семантики системы 11й11Х в случае применения одной нити. Во-вторых, при использовании многонитевых процессов системный вызов обязан вести себя приемлемым образом, не уходя далеко от его семантики на однонитевых системах.
Помня об этих рекомендациях, давайте проведем анализ некоторых важнейших системных вызовов, которые необходимо изменить для многонитевых реализаций. В традиционных системах 111ч1Х вызов 1огк создает процесс-потомок, являющийся точной копией его родителя. Их единственное различие заключается в необходимости отличия потомка от его родителя. Семантика вызова 1ой полностью отвечает требованиям однонитевого процесса. В случае многонитевых процессов имеется дополнительный параметр, позволяющий дублировать либо все 1.%'Р родителя, либо только тот из них, что вызвал функцию ГогЕ. Представьте, что вызову 5ой необходимо произвести копирование вызываюшего его 1.'т1гР в новый процесс, и только его.