Э. Таненбаум - Архитектура компьютера (1127755), страница 138
Текст из файла (страница 138)
Для решения проблемы можно создать несколько программных потоков в одном процессе, которые разделяют общую кэш-память веб-страниц. Если один из программных потоков блокируется, новые запросы могут обрабатываться другими программными потоками. Предотвратить блокировку процессов можно и без использования программных потоков. Для этого потребуется несколько процессов, но тогда придется продублировать кэш, а это несколько расточительно, поскольку объем памяти ограничен. Стандарт системы ())ь(1Х на программные потоки называется рс(сгеас)з и определяется в РО31Х (Р1003.1С).
Он описывает вызовы для управления программными потоками и их синхронизации. В стандарте ничего не сказано о том, должно ли управлять программными потоками ядро, или они должны функционировать только в пользовательском пространстве. Наиболее распространенные функции для работы с программными потоками приведены в табл. 6.9. Таблица 6.9. Основные функции для работы с программными потоками, определенные в стандарте РО81Х Функция Описание ртьгеаб сгеаСе Удаление мьютекса Блокирование мьютекса Разблокирование мьютекса Создание условной переменной Удаление условной переменной Давайте рассмотрим эти вызовы.
Первый вызов, рсСсгеаб сгеате, создает новый программный поток. После выполнения этой процедуры в адресном пространстве появляется на один программный поток болыпе. Программный поток, который выполнил свою работу, вызывает функцию рССсгеаб ехСт. Если потоку нужно подождать, пока другой поток окончит работу, он вызывает функцию ртСсгеаб ЗоСп. Если этот другой программный поток уже закончил свою работу, вызов ртйгеаб .соСп немедленно завершается. В противном случае он блокируется. Программные потоки можно синхронизировать с помощью специальных объектов, которые называются мьютексами (пшсехез). Обычно мьютекс управляет каким-либо ресурсом (например, буфером, разделенным между двумя программными потоками).
Для того чтобы в конкретный момент времени только один поток мог получать доступ к общему ресурсу, потоки должны блокировать мьютекс перед использованием ресурса и разблокировать его после завершения ртьгеаб ехд рщгеаб 1осп РСПгеаб гпиСех ап рбтгеаб пшсех бевсгоу ргвгеасс пшСех 1осК ргьгеаб псцСех оп1осК ртвгеаб сопб 1п!С ртьгеаб сопб безггоу ртвгеаб сопб тта1С ртьгеаб сопб з1рпа1 Создание нового программного потока в адресном пространстве вызывающей процедуры Завершение программного потока Ожидание завершения программного потока Создание нового мьютекса Ждет условную переменную Разблокирование одного из программных потоков, ожидающего условной переменной 546 Глава 6. Уровень операционной системы работы с ним. Так можно избежать состояния гонок, поскольку этому протоколу подчиняются все программные потоки. Мьютексы похожи на бинарные семафоры (то есть семафоры, которые могут принимать только два значения: 0 или 1).
Мьютексы можно создавать и разрушать вызовами ртпгеао аитех 1п11 и РФгеаб ац1ех без1гоу соответственно. Мьютекс может находиться в одном из двух состояний: заблокированном и незаблокированном. Если программному потоку нужно заблокировать незаблокированный мьютекс, он выполняет вызов рФгеаб ацтех 1ост., а затем продолжает работу. Однако если программный поток попытается заблокировать уже заблокированный мьютекс, поток приостанавливается. Когда поток, который в данный момент использует общий ресурс, завершит работу с этим ресурсом, он должен разблокировать соответствующий мьютекс вызовом ртпгеад ацтех ип1осР. Мьютексы предназначены для кратковременной блокировки (например, для защиты общей переменной), но не предназначены для длительной синхронизации (например, для ожидания, пока освободится накопитель на магнитной ленте).
Для длительной синхронизации существуют условные переменные (сопт1й1оп чаг1аЫез). Эти переменные создаются и удаляются вызовами ртпгеай сопй 1п11 и РФгеаб сопй без1гоу соответственно. Условная переменная связана с двумя программными потоками: ожидающим и сигнальным. Если, например, программный поток обнаруживает, что накопитель на магнитной ленте, который ему нужен, в данный момент занят, этот поток выполняет для условной переменной вызов РФгеаб сопб на11.
Когда поток, который использует накопитель на магнитной ленте, завершает свою работу с этим устройством (а это может произойти через несколько часов), он сигнализирует об этом вызовом рФгеао сопй з1дпа1. Это позволяет разблокировать ровно один поток — тот, который ожидает эту условную переменную. При отсутствии программных потоков, ожидающих эту переменную, сигнал пропадает.
У условных переменных нет счетчика, как у семафоров. Отметим, что с потоками, мьютексами и условными переменными можно выполнять и некоторые другие операции. Управление процессами в %1йпдовгв ХР %1пг)отчз ХР поддерживает несколько процессов, которые могут взаимодействовать и синхронизироваться. Каждый процесс содержит по крайней мере один программный поток, который, в свою очередь, содержит по крайней мере один легковесный поток, или волокно (ЙЬег). Процессы, программные потоки и волокна в совокупности представляют собой инструменты поддержания параллелизма в одно- и многопроцессорных системах.
Новые процессы создаются с помощью функции Сгеа1еРгосезз АР1. Эта функция имеет 10 аргументов, у каждого из которых есть множество параметров. Очевидно, что такая система гораздо сложнее соответствующей схемы ~Л~ПХ, где функция 1огЕ вообще не имеет аргументов, а у ехес их всего три: указатели на имя выполняемого файла, на массив параметров командной строки и на строку описания конфигурации. Ниже перечислены 10 аргументов функции Сгеа1еРгосезз: + указатель на имя исполняемого файла; + сама командная строка (без синтаксического разбора); + указатель на дескриптор безопасности данного процесса; Примеры операционных систем 547 + указатель на дескриптор безопасности исходного программного потока; + бит, который сообщает, наследует ли новый процесс описатели родительского процесса; + различные флаги (например, ошибки, приоритета, отладки, консолей); + указатель на строки описания конфигурации; + указатель на имя рабочего каталога нового процесса; + указатель на структуру, которая описывает исходное окно на экране; + указатель на структуру, которая возвращает 18 значений вызывающей процедуре.
В %'1пцотчз ХР нет никакой иерархии родительских дочерних процессов. Все процессы создаются равными. Однако поскольку одним из 18 параметров, возвращаемых исходному процессу, является описатель нового процесса (который дает возможность контролировать новый процесс), здесь существует внутренняя иерархия в том смысле, что определенные процессы содержат описатели других процессов. Эти описатели нельзя просто непосредственно передавать другим процессам, но процесс может сделать определенный описатель доступным для другого процесса, а затем передать ему этот описатель, так что внутренняя иерархия процессов не может сохраняться долго. Каждый процесс в Ж(пцотгз ХР создается с одним программным потоком, но позднее этот процесс может создать еще несколько таких потоков.
Создать программный поток проще, чем процесс, поскольку вызов СгеаСеТИгеаб имеет всего 6 параметров вместо 10: дескриптор безопасности, размер стека, начальный адрес, пользовательский параметр, начальное состояние потока (готов к работе или блокирован) и идентификатор потока. Поскольку созданием потоков занимается ядро, оно располагает информацией обо всех программных потоках (иными словами, их реализация не ограничивается пользовательским пространством, как в некоторых других системах). Когда ядро выполняет синхронизацию, оно вызывает не только процесс, который должен запускаться следующим, но и программный поток этого процесса.
Это значит, что ядро всегда знает, какие программные потоки блокированы, а какие — нет. Так как программные потоки являются объектами ядра, они имеют дескрипторы безопасности и описатели. Поскольку описатели разрешается передавать другому процессу, можно сделать так, чтобы один процесс управлял программными потоками другого процесса.
Эта особенность может понадобиться, например, для отладчиков. Создавать программные потоки в %'1пдоч з ХР довольно расточительно, поскольку для этого требуется войти в ядро, а затем выйти из него. Чтобы избежать этого, в ЪЪ'(пс(оъ'з ХР предусмотрены волокна, которые похожи на программные потоки, но выполняются и синхронизируются в пользовательском пространстве программой, которая их создает. Каждый программный поток может иметь несколько волокон, точно так же как процесс может иметь несколько программных потоков, только в данном случае, когда волокно блокируется, оно встает в очередь заблокированных волокон и выбирает другое волокно для работы в своем и программном потоке.
Ядро не знает об этом переходе, поскольку поток продолжает выполняться, даже если сначала в нем работало одно волокно, а затем другое. 548 Глава б. Уровень операционной системы Ядро управляет процессами и программными потоками, но не управляет волокнами. Волокна могут пригодиться, например, в том случае, когда программы, которые имеют собственные программные потоки, переносятся в %~1п6отчз ХР. Процессы могут взаимодействовать друг с другом разными способами: через каналы, именованные каналы, почтовые слоты, сокеты, удаленные вызовы процедур, общие файлы. Каналы бывают двух видов; байтов и сообщений.
Тип выбирается во время создания. Каналы байтов работают так же, как в 1Л~ПХ. Каналы сообщений сохраняют границы сообщений, поэтому четыре записи по 128 байт считываются из канала как четыре сообщения по 128 байт (а не как одно сообщение размером 512 байт, как в случае с каналами байтов). Кроме того, существуют именованные каналы, которые тоже бывают двух видов. Именованные каналы могут использоваться в сети, а обычные каналы — нет. Почтовые слоты (шш1з1ог) — это атрибут исключительно Ъ%пботтз ХР (в 1ЛЧ1Х их нет). Они во многом похожи на каналы, хотя не во всем. Во-первых, они односторонние, а каналы — двухсторонние.
Их можно использовать в сети, но они не гарантируют доставку. Наконец, они поддерживают широковещательную рассылку сообщений нескольким получателям, а не только одному. Сокеты похожи на каналы, но они обычно соединяют процессы на разных машинах, хотя их можно применять и для соединения процессов на одной машине. Вообще говоря, соединение через сокет ненамного лучше связи через обычный или именованный канал.
Удаленные вызовы процедур позволяют процессу А дать процессу В команду совершить вызов процедуры в адресном пространстве В от имени А и возвратить результат процессу А. Здесь существуют различные ограничения на параметры вызова Например, передача указателя другому процессу не имеет никакого смысла. Наконец, процессы могут разделять общую память путем одновременного отображения на память одного и того же файла. Тогда все записи, порожденные одним процессом, появятся в адресном пространстве других процессов. Применяя такой механизм, можно легко реализовать общий (разделяемый) буфер, который мы описывали в примере с процессом-производителем и процессом-потребителем. Ж(пботчз ХР предоставляет множество механизмов синхронизации (семафоры, мьютексы, критические секции, события).