
- •Операционные системы для программиста
- •Введение
- •1. Основные понятия
- •1.1. Понятие операционной системы
- •1.2. Системные соглашения для доступа к функциям ос
- •1.3. Особенности разработки программ в базовых ос
- •1.4. Командный интерфейс пользователя в ос
- •1.5. Информация об ошибках системной функции
- •2. Программный доступ к файловой системе
- •2.1. Понятия дескрипторов, идентификаторов и хэндлов
- •2.2. Ввод и вывод в стандартные файлы.
- •2.3. Базовые средства использования файлов
- •2.4. Многопользовательская блокировка файлов
- •2.5. Установка произвольной позиции в файле
- •3. Принципы построения ос
- •3.1. Модульная структура построения ос
- •3.2. Использование прерываний в ос
- •3.3. Управление системными ресурсами
- •3.4 Строение ядра операционной системы
- •3.5. Структура операционной системы типа Windows nt
- •4. Многофункциональный консольный вывод
- •4.1. Функции управления курсором
- •4.2. Многократный вывод символов и атрибутов
- •4.3. Вывод в произвольную позицию экрана
- •4.4. Ввод данных, размещенных предварительно на экране
- •5. Системные функции ввода для консольных устройств
- •5.1. Системные функции ввода текстовых строк
- •5.2. Событийно-управляемый ввод
- •5.3. Системные функции ввода с клавиатуры
- •5.4. Опрос ввода с клавиатуры в программе
- •5.5. Системные функции мыши для текстового режима
- •6. Файловые системы
- •6.1. Структуры файловых систем для пользователя
- •6.2. Методы распределения внешней памяти
- •6.3. Принципы построения файловых систем типа fat
- •6.4. Современные модификации файловой системы fat
- •6.5. Особенности построения файловой системы hpfs
- •6.6. Принципы построения файловой системы ntfs
- •6.7. Особенности строения файловых систем для Unix
- •6.8. Программный опрос файловой системы
- •7. Обеспечение множественности процессов
- •7.1. Основные понятия теории вычислительных процессов
- •7.2. Программное порождение процессов
- •7.3. Уничтожение процессов
- •7.4. Ожидание завершения процессов
- •8. Многопоточное функционирование ос
- •8.1. Понятие нити и связь Хе с процессом
- •8.2. Создание нитей (thread) в программе
- •8.3. Уничтожение нитей
- •8.4. Приостановка и повторный запуск нити
- •8.5. Ожидание завершения нити
- •9. Средства взаимодействия программных единиц
- •9.1. Абстрактные критические секции
- •9.2. Абстрактные семафоры
- •9.3. Семафоры взаимоисключения
- •9.4. Семафоры событий
- •9.5. Средства группового ожидания
- •9.6. Программные критические секции
- •9.7. Программные семафоры с внутренним счетчиком
- •10. Управление памятью
- •10.1. Виртуальная память
- •10.2. ЏодкРчка страниц для реализациШ виртуальной памяти
- •10.3. Системные функции распределения памяти
- •10.4. Совместное использование памяти
- •10.5. Отображение файлов в оперативную память
- •10.6. Динамически распределяемая память
- •11. Средства коммуникации процессов
- •11.1. Неименованные коммуникационные каналы Unix
- •11.2. Переназначение хэндлов для доступа к каналу
- •11.3. Неименованные каналы в Windows
- •11.4. Именованные каналы в Windows nt
- •11.5. Именованные каналы в Unix
- •12. Взаимодействие пользователя с ос
- •12.1. Интерфейсы операционных систем
- •12.2. Командные и операционные оболочки (shells)
- •12.3. Основные команды базовых операционных систем
- •12.4. Групповое выполнение и фоновый запуск команд
- •12.5. Стандартный ввод-вывод и конвейеры командной строки
- •12.6. Командные файлы и сценарии
- •Библиографический список
8. Многопоточное функционирование ос
8.1. Понятие нити и связь Хе с процессом
В современных оперРционных системах широко используются нити (thread), называемые несколько неточно в русском переводе также потоками. Это понятие возникло как результат развития понятия абстрактного процесса. Оказалось, что иногда целесообразно процесс – как некоторую общность программного выполнения, имеющую прикладную цель, – разбить на части, которые выполнялись бы параллельно, конкурируя за главный ресурс – процессор, но в остальном выполняли бы общую работу. Можно подойти к осознанию понятия процесса с другой стороны. Абстрактные процессы теоретически разделяют на конкурирующие и кооперативные. Конкурирующие процессы по существу мешают друг другу, но в совокупности выполняют много работ одновременно. Кооперативные процессы выполняют по частям общую работу совместно. Организационно-техническое объединение (под одной "крышей" обобщенного процесса) аналогов кооперативных процессов и составляет существо объединения нитей в одном процессе.
Процесс в современных ОС – это владелец всех основных ресурсов кооперативно работающих нитей. У этих нитей – общее виртуальное адресное пространство, у них общие дескрипторы (управляющие блоки – описатели внутри служебных областей ОС) и соответствующие им хэндлы, причем дескрипторы и хэндлы всевозможных допустимых в ОС объектов: файлов, созданных дочерних процессов, графических окон, семафоров и т.п.). Практически нити одного процесса используют глобальные переменные, в которые каждая из нитей может записывать данные или брать их оттуда. Нити пользуются процессором компьютера по очереди, так что он не принадлежит ни одной из них, но и не принадлежит самому процессу.
Чем же владеет отдельная нить? Нити принадлежит только текущая совокупность значений в аппаратных узлах хранения информации (регистрах) и локальные переменные подпрограмм. Текущую совокупность значений в аппаратных узлах хранения информации называют контекстом задачи. Когда происходит переключение между задачами (нитями), запоминается контекст приостанавливаемой задачи и восстанавливается из места сохранения контекст запускаемой на процессор задачи. В современной архитектуре процессоров много внимания уделяется аппаратной реализации сохранения контекста, его восстановлению и переключению между задачами. Зачем необходимо запоминать и восстанавливать контекст задачи? По той же причине, по которой сохраняется и восстанавливается содержимое аппаратных узлов при возникновении прерывания.
Обычно нить своей работой реализует действия одной из процедур программы. Теоретически любой нити процесса доступны все части программы процесса, в частности, все его процедуры, но реально работа организуется так, чтобы нити отвечала отдельная процедура. Учитывая, что процедуре для нормальной работы необходимы локальные переменные, становится понятным закрепление области этих переменных за нитью. Объект хранения локальных переменных (вместе со служебной информацией при вызове подпрограмм) называют стеком. (Более точное понятие стека программы формируется только с помощью архитектуры процессора.) Этот стек в действительности является частью оперативной памяти, он используется не только программно, но и аппаратно, в частности, при реализации прерываний. Стек процедуры является неотъемлемой частью ресурсов, принадлежащих процедуре. (Более точным термином является кадр стека для процедуры или фрейм стека.)
Очень описательно, но не очень точно соотношение между процессом и нитью можно представить аналогией между собственником земли и его наемными работниками. Как минимум, собственник выполняет организаторскую и контролирующую работу (главная нить процесса), но для более эффективного использования ресурсов привлекает еще наемных работников (остальные нити в процессе).
При разработке многопоточных приложений следует иметь в виду необходимость явного указания для системы разработки, что данное приложение будет использовать более одной нити. Для таких приложений в процессе построения исполняемого файла подключаются специальные библиотеки подпрограмм.
Для задания многопоточного приложения как результата разработки в системах программирования Borland Inc. (Inprise Inc.) при использовании командного вызова компилятора следует обязательно использовать опцию -tWM, так что вызов компилятора для построения исполняемой программы из файла prog.c будет записываться в виде
BCC32 -tWM prog.c
Для компиляции исходного файла в системе MS Visual C++ с помощью компилятора CL.EXE этого пакета следует использовать опцию /MT, так что аналогичный вызов компилятора будет иметь вид
CL /MT prog.c
При использовании интегрированных систем разработки нужно учитывать необходимость установки флажка многопоточного приложения (флажка Multithread) в соответствующем диалоговом окне окна цели (target) разработки. В частности, в среде разработки Borland C++ этот флажок необходимо установить в окне TargetExpert с заголовком New Target, возникающим после выбора подпункта New в пункте Project меню, выпадающего из пункта File главного меню.
При разработке многопоточных программ для Linux следует указывать соответствующую библиотеку поддержки. Такое указание может задаваться в одной из двух основных форм. Первая из них явно задает библиотеку и имеет вид
gcc prog.c /usr/lib/libpthread
а вторая задает эту же библиотеку неявно и записывается в виде
gcc prog.c -lpthread
Естественно, что при этом могут быть использованы и другие опции вызова компилятора, в частности, явное именование результирующего исполняемого файла и добавление отладочной информации.