Глава_1 (Методическое пособие по Операционным системам)
Описание файла
Файл "Глава_1" внутри архива находится в следующих папках: Методическое пособие по Операционным системам, Операционне системы. Документ из архива "Методическое пособие по Операционным системам", который расположен в категории "". Всё это находится в предмете "операционные системы" из 7 семестр, которые можно найти в файловом архиве РТУ МИРЭА. Не смотря на прямую связь этого архива с РТУ МИРЭА, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "операционные системы" в общих файлах.
Онлайн просмотр документа "Глава_1"
Текст из документа "Глава_1"
72
Но было бы крайне неудобно хранить каждый раздел и параграф хранить в собственном файле- в случае глобальных изменений пришлось бы редактировать сотни файлов. Например, если предполагаемый стандарт ххх был утвержден только перед отправкой книги в печать, придется заменять «Черновой стандарт ххх» на «Стандарт ххх» в последнюю минуту. Эта операция делается одной командой в случае одного файла и, напротив, займет очень много времени, если придется редактировать каждый из 300 файлов, на которые разбита книга.
Теперь представьте себе, что произойдет, если пользователь удалит одно предложение на первой странице документа, в котором 800 страниц. Пользователь перечитал эту страницу и решил исправить предложение на 600-й странице. Он дает команду текстовому редактору перейти на страницу с номером 600 (например, задав поиск фразы, встречающейся только на этой странице). Текстовому редактору придется переформатировать весь документ вплоть до 600 страницы, поскольку до форматирования он не будет знать, где начинается эта страница. Это может занять довольно много времени и вряд ли обрадует пользователя.
В этом случае помогут потоки. Пусть текстовый редактор написан в виде двухпоточной программы. Один поток взаимодействуете пользователем, а второй переформатирует документ в фоновом режиме. Как только предложение на первой странице было удалено, интерактивный поток дает команду фоновому потоку переформатировать весь документ. В то время как первый поток продолжает отслеживать и выполнять команды с клавиатуры или мыши — предположим, прокручивает первую страницу, второй поток быстро переформатирует книгу. Немного везения — и форматирование будет закончено раньше, чем пользователь захочет перейти к 600 странице, и тогда команда будет выполнена мгновенно.
Раз уж мы об этом задумались, почему бы не добавить третий поток? Большинство текстовых редакторов автоматически сохраняет редактируемый текст раз в несколько минут, чтобы пользователь не лишился плодов работы целого дня в случае аварийного завершения программы, отказа системы или перебоев с питанием. Этим может заниматься третий поток, не отвлекая два оставшихся (рис. 2.6).
Если бы программа была однопоточной, тогда при каждой операции сохранения файла все команды с клавиатуры и мыши игнорировались до окончания дисковой операции. У пользователя это создало бы впечатление низкой производительности. В качестве альтернативы команды с клавиатуры и мыши могут прерывать сохранение файла, обеспечивая высокую производительность, но приводя к сложной программной модели, управляемой прерываниями. Программная модель с тремя потоками существенно проще. Первый поток взаимодействует с пользователем, второй при необходимости переформатирует документ, а третий периодически сохраняет на диске содержимое оперативной памяти.
Очевидно, что в этом случае модель с тремя процессами не подойдет, поскольку всем трем необходимо работать с одним и тем же документом. Три же потока совместно используют общую намять, и все три имеют доступ к документу.
Ситуация выглядит точно так же в случае многих других интерактивных программ. Динамическая электронная таблица - программа, позволяющая пользователю работать с матрицей, некоторые элементы которой заданы пользователем. Остальные элементы вычисляются на основе заданных элементов с использованием достаточно сложных формул. Если пользователь изменяет один элемент матрицы, это приводит к пересчету многих других элементов. Пока один поток занят пересчетом элементов в фоновом режиме, другой может позволить пользователю в это время вносить дальнейшие изменения. А третий поток может периодически сохранять резервную копию файла на диске.
Теперь давайте рассмотрим еще одну ситуацию, в которой необходимы потоки; сервер web-сайта. На сервер приходят запросы, и клиенту отсылается содержимое запрашиваемых web-страниц. У большинства web-сайтов некоторые страницы существенно более посещаемы, чем другие. Например, главная страница компании Sony посещается гораздо чаще, чем страница с техническими спецификациями конкретных моделей записывающих видеокамер. Для повышения эффективности работы сервер использует эту особенность, храня содержимое особо популярных страниц в основной памяти (чтобы не надо было каждый раз обращаться , за ними на диск). Этот раздел памяти называется кэш, и он используется также во многих других ситуациях.
На рис. 2.7 представлен один из способов организации web-сервера. Один поток, называемый диспетчером, считывает приходящие по сети запросы. После этого он находит свободный (то есть блокированный) рабочий поток и передаст ему запрос, скажем, записывая указатель сообщения в специальное слово, связанное с каждым потоком. Затем диспетчер активизирует ждущий поток, переводя его из состояния блокировки в состояние готовности.
После активации рабочий поток проверяет возможность удовлетворения запроса в кэше web-страниц, к которому имеют доступ все потоки. В случае отрицательного ответа поток начинает операцию чтения read, чтобы считать страницу с диска, и блокируется до завершения этой операции. Когда рабочий поток блокируется, для запуска выбирается следующий поток, им может оказаться диспетчер или другой готовый рабочий поток.
Эта модели позволяет создать сервер в виде набора последовательных потоков. Программа диспетчера состоит из бесконечного цикла, в который входит получение запроса и передача его рабочему потоку. Программа каждого рабочего потока состоит из бесконечного цикла, включающего получение запроса от диспетчера и проверку кэша на наличие запрашиваемой страницы. При наличии страницы в кэше она отсылается клиенту, и рабочий процесс блокируется в ожидании нового запроса. При отсутствии страницы в кэше она считывается с диска, отсылается клиенту, и рабочий процесс блокируется в ожидании нового запроса.
Приблизительный набросок программы представлен на рис. 2.8. Здесь и в дальнейшем TRUE предполагается константой, равной 1. Переменные buf и page являются структурами, подходящими соответственно для хранения запроса и web-страницы.
Теперь рассмотрим, как можно было написать web-сервер в отсутствие потоков. Одна из возможностей — заставить его работать как один поток. Основной цикл получает запрос, проверяет его и удовлетворяет, затем переходит к следующему. Пока web-страница считывается с диска, сервер простаивает и не обрабатывает другие поступающие запросы. Если сервер расположен на выделенном компьютере—а чаще всего именно так и бывает, — процессор простаивает, пока web-страница считывается с диска. В результате в единицу времени однопоточное приложение может обрабатывать существенно меньшее число запросов. Таким образом, использование нескольких потоков дает заметное увеличение производительности, хотя каждый поток программируется последовательно, обычным способом.
Итак, мы рассмотрели два возможных варианта: Web-сервер с одним потоком и несколькими потоками. Представьте себе, что многопоточная система невозможна, но хочется увеличить эффективность системы с одним потоком. Возможен третий вариант wеb-сервера в случае существования версии системного запроса read без блокировки. На сервер приходит запрос, его считывает и проверяет единственный поток. Если запрашиваемая web-страница есть в кэше — хорошо, если нет— запускается дисковая операция без блокировки. Сервер записывает в таблицу текущее состояние запроса и переходит к следующему событию. Оно может быть как новым запросом, так и ответом предыдущей операции. В случае нового запроса он начинает обрабатываться, в противном случае соответствующая информация считывается из таблицы и формируется ответ. В случае процедуры ввода-вывода с диска без блокировки ответ может иметь форму сигнала или прерывания.
При такой схеме модель «последовательных процессов», которая была справедлива в первых двух ситуациях, не действует. Состояние программы должно явно сохраняться и восстанавливаться в таблице каждый раз, когда сервер переключается между запросами. Фактически мы имитируем потоки и стеки, причем не самым простым способом. Такая модель, в которой каждому расчету соответствует сохраненное состояние и есть несколько событий, которые могут изменить, это состояние, называется машиной с конечным числом состояний или конечным автоматом. Эта модель широко используется в программировании.
Теперь должно быть ясно, какие преимущества приносят потоки. Они дают возможность сохранить модель последовательных процессов, выполняющих блокирующие системные запросы (например, для ввода-вывода с диска), и тем не менее добиться параллелизма. Системные запросы с блокировкой упрощают программирование, а параллелизм увеличивает производительность. Однопоточный сервер сохраняет простоту программирования, связанную с наличием блокирующих системных запросов, но уступает в производительности. Модель конечного автомата существенно повышает производительность при помощи параллелизма, но использует системные запросы без блокировки, что усложняет программирование. Эти модели представлены в табл. 2.4.
Таблица 2.4. Три способа конструирования сервера |
Модель Характеристики |
Потоки Параллелизм, системные запросы с блокировкой Процесс с одним потоком Нет параллелизма, системные запросы о блокировкой Конечный автомат Параллелизм, системные запросы без блокировки, прерывания |
Третий пример необходимости потоков — приложения, оперирующие большим количеством данных. Обычно считывается блок данных, обрабатывается и снова записывается. Проблема состоит в том, что при наличии только системных запросов с блокировкой процесс будет блокироваться при чтении и записи данных. Необходимо избегать простоя процессора, особенно при таком большом объеме вычислений.
Решение проблемы — в потоках. Процесс можно разбить на входной поток, обрабатывающий поток и выходной поток. Входной поток считывает данные и помещает их во входной буфер. Обрабатывающий поток считывает данные из входного буфера, обрабатывает их и помещает в выходной буфер, а выходной поток считывает их оттуда и записывает обратно на диск. В такой модели считывание данных, обработка и запись происходят одновременно. Разумеется, это возможно лишь в том случае, когда системные вызовы блокируют только вызывающий поток, а не весь процесс.
Реализация потоков в пространстве пользователя
Есть два основных способа реализации пакета потоков: в пространстве пользователя и ядре. Выбор между ними остается спорным вопросом, и возможна смешанная реализация. Мы рассмотрим оба способа, а также их преимущества и недостатки.
Первый метод состоит в размещении пакета потоков целиком в пространстве пользователя. При этом ядро о потоках ничего не знает и управляет обычными, однопоточными процессами. Наиболее очевидное преимущество этой модели состоит в том, что пакет потоков на уровне пользователя можно реализовать даже в операционной системе, не поддерживающей потоки. Все операционные системы когда-то относились к этой категории, а некоторые относятся до сих пор.
Подобные реализации имеют в своей основе одинаковую общую схему, представленную на рис. 2.9, а. Потоки работают поверх системы поддержки исполнения программ, которая является набором процедур, управляющих потоками. С четырьмя из них мы уже знакомы: thread_create, thread exit, thread wait и thread_yield, но обычно их больше. Если управление потоками происходит в пространстве пользователя, каждому процессу необходима собственная таблица потоков для отслеживания потоков в процессе. Эта таблица аналогична таблице процессов, с той лишь разницей, что она отcлеживает лишь характеристики потоков, такие как счетчик команд, указатель вершины стека, регистры, состояние и т. п. Когда поток переходит в состояние готовности или блокировки, вся информация, необходимая для повторного запуска, хранится в таблице потоков подобному тому, как в ядре хранится информация о процессах в таблице процессов. Когда поток, ожидая окончания действия другого потока в том же процессе, делает нечто, что может привести к локальной блокировке, он вызывает процедуру системы поддержки исполнения программ. Процедура проверяет необходимость блокирования потока. В этом случае процедура сохраняет регистры потока в таблице потоков, ищет в таблице поток, готовый к запуску, и загружает его сохраненные значения в регистры машины. Как только указатель стека и счетчик команд переключены, работа нового потока возобновляется автоматически. Если у процессора есть команда, позволяющая за одну инструкцию сохранить все регистры и еще одна, чтобы загрузить их все заново, переключение потоков может быть выполнено с помощью очень небольшого количества инструкций. Такое переключение потоков по крайней мере на порядок быстрее, чем переключения в режим ядра и является серьезным аргументом в пользу управления потоками в пространстве пользователя.