Главная страница Межпроцессное взаимодействие (состязание) Таблица 2.1. Некоторые поля типового элемента таблицы процессов Управление процессом Регистры ♦ Счетчик команд ♦ Слово состояния программы ♦ Указатель стека > Состояние процесса ♦ Приоритет > Использованное процессорное время > Процессорное время дочернего процесса 4- Время следующего аварийного сигнала Указатели очереди сообщений ♦ Биты действующих сигналов ♦ Идентификатор процесса ♦ Различные флаги Управление памятью Указатель на текстовый сегмент 4- Указатель на сегмент данных 4- Указатель на сегмент стека ♦ Статус завершения Состояние сигнешов ♦ Идентификатор процесса 4 Родительский процесс 4 Реальный UID 4 Эффективный GID 4 Реальный GID 4 Эффективный GID 4 Битовые маски для сигналов 4 Различные битовые флаги Управление файлами Маска UMASK 4 Корневой каталог 4 Рабочий каталог 4 Дескрипторы файла 4 Эффективный идентификатор пользователя 4 Эффективный идентификатор группы 4 Параметры системного вызова 4 Различные битовые флаги Обработка любого прерывания начинается с сохранения регистров, часто в блоке управления текущим процессом в таблице процессов. Затем информация, помещенная в стек прерыванием, удаляется, и указатель стека переставляется на временный стек, используемый программой обработки процесса. Такие действия, как сохранение регистров и установка указателя стека, невозможно даже выразить на языке высокого уровня (например, на С). Поэтому они выполняются небольшой программой на ассемблере, обычно одинаковой для всех прерываний, поскольку процедура сохранения регистров не зависит от причины возникновения прерывания. Взаимодействие между процессами в MINIX организуется при помощи сообщений, таким образом, следующий шаг - формирование уведомления дисковому процессу, который ожидает информации от системы в заблокированном состоянии. В сообщении указывается, что произошло именно прерывание, чтобы его можно было отличить от сообщений других пользовательских процессов, запрашивающих чтение дисковых блоков и т. п. После этого с процесса снимается блокировка и делается вызов планировщика. В MINIX у процессов могут быть разные приоритеты, с целью дать обработчикам ввода/вывода преимущество перед обычными пользовательскими программами. Соответственно, если в данный момент у дискового процесса наибольший приоритет, для запуска будет выбран этот процесс. Если же приоритет прерванного процесса не меньше, то будет запущен он, а дисковому придется немного подождать. По завершении своей работы эта программа вызывает процедуру на языке С, которая выполняет все остальные действия, связанные с конкретным прерыва- нием. (Мы предполагаем, что операционная система написана на С, что является стандартным решением для всех существующих ОС.) Схема обработки прерывания нижним уровнем операционной системы и действия планировщика представлены ниже. Следует отметить, что частности могут несколько варьироваться от системы к системе. 1. Аппаратное обеспечение сохраняет в стеке счетчик команд и т. п. 2. Аппаратное обеспечение загружает новый счетчик команд из вектора прерываний. 3. Процедура на ассемблере сохраняет регистры. 4. Процедура на ассемблере устанавливает новый стек. 5. Запускается программа обработки прерываний на С. (Она обычно считывает и буферизует входные данные.) 6. Планировщик выбирает следующий процесс. 7. Программа на С передает управление процедуре на ассемблере. 8. Процедура на ассемблере запускает новый процесс. 2.1.3. Нити в традиционных процессах, о которых мы только что говорили, есть только один поток управления и один счетчик команд. Но в некоторых современных операционных системах существует возможность создать несколько потоков управления в одном процессе. Такие потоки обычно называются просто нитями или, иногда, легковесными процессами. На рис. 2.4, а представлены три обычных процесса, у каждого из которых есть собственное адресное пространство и единственный поток управления. На рис. 2.4, б представлен один процесс с тремя потоками управления. В обоих случаях присутствуют три нити, но на рис. 2.4, а каж;1ая из них имеет собственное адресное пространство, а на рис. 2.4, б нити разделяют память вместе. Компьютер Счетчик программы Поток Процесс Компьютер Рис. 2.4. а - три процесса с одиночными потоками управления; б - один процесс с тремя потоками управления В качестве примера приложения, рассчитанного на многопоточность, рассмотрим файловый сервер. Процесс сервера получает запрос на чтение или запись файла, а также отсылает считанные данные или, наоборот, принимает данные для записи. Чтобы увеличить производительность, сервер поддерживает в памяти кэш последних обращений к файлам и, по возможности, пытается работать с ним. Такая ситуация естественным образом ведет к рис. 2.4, б. Поступивший запрос обрабатывается отдельной нитью. Если эта нить по той или иной причине блокируется (например из-за обращения к диску), другие нити могут продолжать работу. Изображенная на рис. 2.4, а модель не подходит, так как здесь отдельные нити не в силах использовать общий кэш в памяти. Другой пример приложения, в котором необходимы потоки управления, - это браузеры, наподобие Netscape или Internet Explorer. Многие веб-страницы оформлены с помощью большого числа маленьких изображений. Чтобы загрузить каждое из них, браузеру необходимо каждый раз создавать новое соединение, и львиная доля времени уходит на процесс установки и завершения этих соединений. Если же один браузер будет использовать несколько потоков, он сможет запрашивать несколько картинок одновременно, что иногда приводит к заметному увеличению скорости, так как для небольших изображений время собственно передачи данных невелико. Когда в памяти имеется несколько нитей, то некоторые из полей, показанных в табл. 2.1, относятся уже не к процессам, а к отдельным нитям. Поэтому необходима дополнительная таблица, каждая запись в которой будет описывать отдельный поток управления. Среди прочих в этой таблице должны быть такие поля, как счетчик команд, регистры и состояние потока. Счетчик команд нужен потому, что нити, как и процессы, могут приостанавливаться и возобновлять свою работу. Поля регистров необходимы по той причине, что значения регистров приостановленной нити необходимо сохранять. Наконец, нити, как и процессы, могут находиться в состоянии выполнения, готовности, а также быть заблокированными. Иногда операционная система не заботится о потоках управления. Другими словами, управление нитями происходит целиком в пользовательском режиме. Например, когда нить блокируется, то, перед тем как остановиться, она решает, какая нить получит управление дальше, и запускает ее. Существуют и широко используются несколько библиотек для поддержки пользовательских нитей, в том числе пакеты POSIX P-Threads и Mach C-Threads. В других системах ОС учитывает существование множества потоков, и, когда одна нить переходит в состояние блокировки, система выбирает следующую, которая получит управление, в том же самом процессе или в другом. Чтобы поддерживать такую функциональность, ядро системы должно хранить таблицу всех нитей в системе, наподобие таблицы процессов. Хотя, на первый взгляд, оба варианта могут показаться равносильными, между ними есть заметная разница в производительности. Переключение потоков происходит гораздо быстрее, когда оно делается без участия ядра. Этот факт - серьезный аргумент за пользовательские нити. С другой стороны, когда одна из
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |