![](/user_photo/2706_HbeT2.jpg)
- •Оглавление
- •Введение
- •Цель работы
- •1 Процессы, задания и потоки.
- •1.1 Процессы.
- •1.2 Задания.
- •1.3 Потоки.
- •2. Управление памятью в операционных системах
- •2.1 Память и отображения, виртуальное адресное пространство
- •2.2 Виртуальное адресное пространство
- •2.3 Распределение памяти статическими и динамическими разделами
- •2.4 Разделы с фиксированными границами
- •2.5 Разделы с подвижными границами
- •2.6 Сегментная, страничная и сегментно-страничная организация памяти.
- •3 Динамически подключаемые библиотеки.
- •4 Обработка исключений
- •4.1 Обработчики завершения
- •4.2 Примеры использования обработчиков завершения
- •5 Операции с окнами
- •5.1 Оконные сообщения
- •5.2 Очередь сообщений потока
- •5.3 Посылка асинхронных сообщений в очередь потока
- •5.4 Посылка синхронных сообщений окну
- •Приложение 1. Справочник api-функций и сообщений Windows.
- •Приложение 2. Темы курсовой работы.
- •Список литературы
- •Литература
1.2 Задания.
Группу процессов зачастую нужно рассматривать как единую сущность. Например, когда Вы командуете Microsoft Developer Studio собрать проект, он порождает процесс Ct.exe, а тот в свою очередь может создать другие процессы (скажем, для дополнительных проходов компилятора). Но, если Вы пожелаете прервать сборку, Developer Studio должен каким-то образом завершить C1.exe и все его дочерние процессы. Решение этой простой (и распространенной) проблемы в Windows было весьма затруднительно, поскольку она не отслеживает родственные связи между процессами. В частности, выполнение дочерних процессов продолжается даже после завершения родительского.
При разработке сервера тоже бывает полезно группировать процессы. Допустим, клиентская программа просит сервер выполнить приложение (которое создает ряд дочерних процессов) и сообщить результаты. Поскольку к серверу может обратиться сразу несколько клиентов, было бы неплохо, если бы он умел как-то ограничивать ресурсы, выделяемые каждому клиенту, и тем самым не давал бы одному клиенту монопольно использовать все серверные ресурсы. Под ограничения могли бы подпадать такие ресурсы, как процессорное время, выделяемое на обработку клиентского запроса, и размеры рабочего набора (working set). Кроме того, у клиентской программы не должно быть возможности завершить работу сервера и т д.
В Windows 2000 введен новый объект ядра — задание job. Он позволяет группировать процессы и помещать их в нечто вроде песочницы, которая определенным образом ограничивает их действия. Относитесь к этому объекту как к контейнеру процессов. Кстати, очень полезно создавать задание и с одним процессом — это позволяет налагать на процесс- ограничения, которые иначе указать нельзя.
Создание нового объекта ядра «задание» выполняется вызовом:
HANDLE CreateJobObject( PSECURITY_ATTRIBUTES psa, PCTSTR pszName);
Как и любая функция, создающая объекты ядра, CreateJobObject принимает в первом параметре информацию о защите и сообщает системе, должна ли она вернуть наследуемый описатель. Параметр pszName позволяет присвоить заданию имя, что бы к нему могли обращаться другие процессы через функцию OpenJobObject.
HANDLE OpenJobObject( DWORD dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);
Закончив работу с объектом-заданием, закройте его описатель, вызвав, как всегда, CloseHandle. Именно так я и делаю в конце своей функции StartRestrictedProcess. Имейте в виду, что закрытие объекта-задания не приводит к автоматическому завершению всех его процессов. На самом деле этот объект просто помечается как подлежащий разрушению, и система уничтожает его только после завершения всех включенных в него процессов
1.3 Потоки.
В любом процессе должен быть хотя бы один поток. Подобно процессам, потоки обладают определенными свойствами, поэтому мы поговорим о функциях, позволяющих обращаться к этим свойствам и при необходимости модифицировать их.
В главе 4.1 сказано, что процесс фактически состоит из двух компонентов объекта ядра "процесс" и адресного пространства так вот, любой поток тоже состоит из двух компонентов:
объекта ядра, через который операционная система управляет потоком. Там же хранится статистическая информация о потоке;
стека потока, который содержит параметры всех функций и локальные переменные, необходимые потоку для выполнения кода.
Процессы инертны. Процесс ничего не исполняет, он просто служит контейнером потоков. Потоки всегда создаются в контексте какого-либо процесса, и вся их жизнь проходит только в его границах. На практике это означает, что потоки исполняют код и манипулируют данными в адресном пространстве процесса. Поэтому, если два и более потоков выполняется в контексте одного процесса, все они делят одно адресное пространство. Потоки могут исполнять один и тот же код и манипулировать одними и теми же данными, а также совместно использовать описатели объектов ядра, поскольку таблица описателей создается не в отдельных потоках, а в процессах.
Как видите, процессы используют куда больше системных ресурсов, чем потоки. Причина кроется в адресном пространстве. Создание виртуального адресного пространства для процесса требует значительных системных ресурсов. При этом ведется масса всяческой статистики, на что уходит немало памяти. В адресное пространство загружаются EXE- и DLL-файлы, а значит, нужны файловые ресурсы. С другой стороны, потоку требуются лишь соответствующий объект ядра и стек, объем статистических сведений о потоке невелик и много памяти не занимает.
Так как потоки расходуют существенно меньше ресурсов, чем процессы, старайтесь решать свои задачи за счет использования дополнительных потоков и избегайте создания новых процессов. Только не принимайте этот совет за жесткое правило — многие проекты как paз лучше реализовать на основе множества процессов Нужно просто помнить об издержках и соразмерять цель и средства.
Поток может быть создан при помощи функции CreateThread. Рассмотрим параметры этой функции.
1-й параметр. Указатель на структуру атрибутов доступа. Имеет значение только для Windows NT. Обычно полагается NULL.
2-й параметр. Размер стека потока. Если параметр равен нулю, то берется размер стека по умолчанию, равный размеру стека родительского потока.
3-й параметр. Указатель на потоковую функцию, с вызова которой начинается исполнение потока.
4-й параметр. Параметр для потоковой функции.
5-й параметр. Флаг, определяющий состояние потока. Если флаг равен 0, то выполнение потока начинается немедленно. Если значение флага потока равно CREATE_SUSPENDED (4H), то поток находится в состояние ожидания и запускается по выполнению функции ResumeThread.
6-й параметр. Указатель на переменную, куда будет помещен дескриптор потока.
Как уже было сказано, выполнение потока начинается с потоковой функции. Окончание работы этой функции приводит к естественному окончанию работы потока. Поток также может закончить свою работу, выполнив функцию ExitThread с указанием кода выхода. Наконец, порождающий поток может закончить работу порожденного потока при помощи функции TerminateThread.