Управление процессами и потоками в windows

Работа операционной системы Windows основана на работе процессов. В этой статье разберём что такое Windows процессы, их свойства, состояния и другое.

Процессы

Процесс стоит воспринимать как контейнер с набором ресурсов для выполнения программы. То есть запускаем мы программу, для неё выделяется часть ресурсов компьютера и эта программа работает с этими ресурсами.

Процессы нужны операционной системе для многозадачности, так как программы работают в своих процессах и не мешают друг другу, при этом по очереди обрабатываются процессором.

Windows процессы состоят из следующего:

  • Закрытое виртуальное адресное пространство, то есть выделенная для процесса часть оперативной памяти, которая называется виртуальной.
  • Исполняемая программа выполняя свой код, помещает его в виртуальную память.
  • Список открытых дескрипторов. Процесс может открывать или создавать объекты, например файлы или другие процессы. Эти объекты нумеруются, и их номера называют дескрипторами. Ссылаться на объект по дескриптору быстрее, чем по имени.
  • Контекст безопасности. Сюда входит пользователь процесса, группа, привилегии, сеанс и другое.
  • Идентификатор процесса, то есть его уникальный номер.
  • Программный поток (как минимум один или несколько). Чтобы процесс хоть что-то делал, в нем должен существовать программный поток. Если потока нет, значит что-то пошло не так, возможно процесс не смог корректно завершиться, или стартовать.

У процессов есть еще очень много свойств которые вы можете посмотреть в «Диспетчере задач» или «Process Explorer«.

Процесс может быть в различных состояниях:

  • Выполняется — обычно все фоновые процессы будут в этом состоянии, а если процесс с окошком, то значит что приложение готово принимать данные от пользователя.
  • Приостановлен — означает что все потоки процесса находятся в приостановленном состоянии. Приложения Windows Apps переходят в это состояние при сворачивании окна для экономии ресурсов.
  • Не отвечает — означает что программный поток не проверял свою очередь сообщений более 5 секунд. Поток может быть занят работой и интенсивно загружать процессор, или может ожидать операции ввода/вывода. При этом окно приложения зависает.

В Windows существуют процессы трёх типов:

  • Приложения. Процессы запущенных приложений. У таких приложений есть окно на рабочем столе, которое вы можете свернуть, развернуть или закрыть.
  • Фоновые процессы. Такие процессы работают в фоне и не имеют окна. Некоторые процессы приложений становятся фоновыми, когда вы сворачиваете их в трей.
  • Процессы Windows. Процессы самой операционной системы, например «Диспетчер печати» или «Проводник».

Дерево процессов

В Windows процессы знают только своих родителей, а более древних предков не знают.

Например у нас есть такое дерево процессов:

Процесс_1
|- Процесс_2
  |- Процесс_3

Если мы завершим дерево процессов «Процесс_1«, то завершатся все процессы. Потому что «Процесс_1» знает про «Процесс_2«, а «Процесс_2» знает про «Процесс_3«.

Если мы вначале завершим «Процесс_2«, а затем завершаем дерево процессов «Процесс_1«, то завершится только «Процесс_1«, так как между «Процесс_1» и «Процесс_3» не останется связи.

Например, запустите командную строку и выполните команду title parrent чтобы изменить заголовок окна и start cmd чтобы запустить второе окно командной строки:

>title parrent
>start cmd

Измените заголовок второго окна на child и из него запустите программу paint:

>title child
>mspaint

В окне командной строке child введите команду exit, окно закроется а paint продолжит работать:

>exit

После этого на рабочем столе останутся два приложения, командная строка parrent и paint. При этом parrent будет являться как бы дедом для paint.

Запустите «Диспетчер задач», на вкладке «Процессы» найдите процесс «Обработчик команд Windows», разверните список и найдите «parrent«. Затем нажмите на нём правой копкой мыши и выберите «Подробно»:

Подробности по процессу parrent

Вы переключитесь на вкладку «Подробно» с выделенным процессом «cmd.exe«. Нажмите правой кнопкой по этому процессу и выберите «Завершить дерево процессов»:

Завершаем дерево процессов в диспетчере задач

Окно командной строки Parrent завершится а Paint останется работать. Так мы убедились что связи между первым процессом и его внуком нет, если у внука нет непосредственного родителя.

Потоки

На центральном процессоре обрабатываются не сами процессы, а программные потоки. Каждый поток, это код загруженный программой. Программа может работать в одном потоке или создавать несколько. Если программа работает в несколько потоков, то она может выполняться на разных ядрах процессора. Посмотреть на потоки можно с помощью программы Process Explorer.

Поток содержит:

  • два стека: для режима ядра и для пользовательского режима;
  • локальную памятью потока (TLS, Thread-Local Storage);
  • уникальный идентификатор потока (TID, Thread ID).

Приложение может создать дополнительный поток, например, когда у приложения есть графический интерфейс, который работает в одном потоке и ожидает от пользователя ввода каких-то данных, а второй поток в это время занимается обработкой других данных.

Изучение активности потока важно, если вам нужно разобраться, почему тот или иной процесс перестал реагировать, а в процессе выполняется большое число потоков. Потоков может быть много в следующих процессах:

  • svchost.exe — главный процесс для служб Windows.
  • dllhost.exe — отвечает за обработку приложений, использующих динамически подключаемые библиотеки. Также отвечает за COM и .NET. И ещё управляет процессами IIS.
  • lsass.exe — отвечает за авторизацию локальных пользователей, попросту говоря без него вход в систему для локальных пользователей будет невозможен.

Волокна и планирование пользовательского режима

Потоки выполняются на центральном процессоре, а за их переключение отвечает планировщик ядра. В связи с тем что такое переключение это затратная операция. В Windows придумали два механизма для сокращения таких затрат: волокна (fibers) и планирование пользовательского режима (UMS, User Mode Scheduling).

Во-первых, поток с помощью специальной функции может превратится в волокно, затем это волокно может породить другие волокна, таким образом образуется группа волокон. Волокна не видимы для ядра и не обращаются к планировщику. Вместо этого они сами договариваются в какой последовательности они будут обращаться к процессору. Но волокна плохо реализованы в Windows, большинство библиотек ничего не знает о существовании волокон. Поэтому волокна могут обрабатываться как потоки и начнутся различные сбои в программе если она использует такие библиотеки.

Потоки UMS (User Mode Scheduling), доступные только в 64-разрядных версиях Windows, предоставляют все основные преимущества волокон при минимуме их недостатков. Потоки UMS обладают собственным состоянием ядра, поэтому они «видимы» для ядра, что позволяет нескольким потокам UMS совместно использовать процессор и конкурировать за него. Работает это следующим образом:

  • Когда двум и более потокам UMS требуется выполнить работу в пользовательском режиме, они сами могут периодически уступать управление другому потоку в пользовательском режиме, не обращаясь к планировщику. Ядро при этом думает что продолжает работать один поток.
  • Когда потоку UMS все таки нужно обратиться к ядру, он переключается на специально выделенный поток режима ядра.

Задания

Задания Windows (Job) позволяют объединить несколько процессов в одну группу. Затем можно этой группой управлять:

  • устанавливать лимиты (на память или процессорное время) для группы процессов входящих в задание;
  • останавливать, приостанавливать, запускать такую группу процессов.

Посмотреть на задания можно с помощью Process Explorer.

Диспетчер задач

Чаще всего для получения информации о процессе мы используем «Диспетчер задач». Запустить его можно разными способами:

  • комбинацией клавиш Ctrl+Shift+Esc;
  • щелчком правой кнопкой мыши на панели задач и выборе «Диспетчер задач»;
  • нажатием клавиш Ctrl+Alt+Del и выборе «Диспетчер задач»;
  • запуском исполняемого файла C:\Windows\system32\Taskmgr.exe.

При первом запуске диспетчера задач он запускается в кратком режиме, при этом видны только процессы имеющие видимое окно. При нажатие на кнопку «Подробнее» откроется полный режим:

Краткий режим Диспетчера задач

В полном режиме на вкладке «Процессы» виден список процессов и информация по ним. Чтобы получить больше информации можно нажать правой кнопкой мышки на заголовке и добавить столбцы:

Диспетчер задач - Добавление столбцов с информацией

Чтобы получить еще больше информации можно нажать правой кнопкой мышки на процессе и выбрать «Подробно». При этом вы переключитесь на вкладку «Подробности» и этот процесс выделится.

На вкладке «Подробности» можно получить ещё больше информации о процессе. А также здесь также можно добавить колонки с дополнительной информацией, для этого нужно щелкнуть правой кнопкой мыши по заголовку и нажать «Выбрать столбцы»:

Выбор столбцов с информацией о процессах на вкладке «Подробности»

Process Explorer

Установка и подготовка к работе

Более подробную информацию о процессах и потоках можно получить с помощью программы Process Explorer из пакета Sysinternals. Его нужно скачать и запустить.

Некоторые возможности Process Explorer:

  • информация по правам процесса: кто владелец процесса, у кого есть доступ к нему;
  • выделение разными цветами процессов и потоков, для удобного восприятия информации:
    • процессы служб — розовый;
    • ваши собственные процессы — синий;
    • новые процессы — зелёный;
    • завершенные процессы — красный;
  • список файлов открытых процессом;
  • возможность приостановки процесса или потока;
  • возможность уничтожения отдельных потоков;
  • поиск процессов создающих наибольшую нагрузку на процессор;
  • отображение списка процессов в виде дерева, а также алфавитная сортировка и сортировка в обратном порядке;
  • возможность посмотреть:
    • число дескрипторов у процесса;
    • активность потоков в процессе;
    • подробную информация о распределении памяти.

Запустите Process Explorer:

Process Explorer

Далее нужно настроить сервер символических имен. Если это не сделать, при двойном щелчке на процессе, на вкладке Threads (потоки) вы получите сообщение о том, что символические имена не настроены:

Предупреждение о не настроенных символических именах

Для начала скачиваем установщик «Пакет SDK для Windows 10».

Устанавливать все не нужно, достаточно при установки выбрать «Debugging Tools for Windows«:

Установка SDK для Windows 10

Для настройки символических имен перейдите в меню Options / Configure / Symbols. Введите путь к библиотеке Dbghelp.dll, которая находится внутри установленного «Пакета SDK для Windows 10» по умолчанию:

  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Dbghelp.dll.

И путь к серверу символической информации:

  • srv*C:\Symbols*http://msdl.microsoft.com/download/symbols

При этом:

  • C:\Symbols — путь к кеширующей локальной папке;
  • http://msdl.microsoft.com/download/symbols — сервер microsoft.

Настройка символический имен в Process Explorer

Некоторые основные настройки Process Explorer:

  • Смена цветового выделения — Options / Configure Colors.
  • Выбор колонок с информацией о процессах — View / Select Columns.
  • Сортировка процессов — нужно щелкнуть на заголовке столбца Process, при первом щелчке сортировка будет в алфавитном порядке, при втором в обратном порядке, при третьем вернется в вид дерева.
  • Просмотр только своих процессов — View / снять галочку Show Processes from All Users.
  • Настройка времени выделения только что запущенных процессов и завершённых — Options / Difference Highlight Duration / введите количество секунд.
  • Чтобы исследователь процесс подробнее можно дважды щелкнуть на нем и посмотреть информацию на различных вкладках.
  • Открыть нижнюю панель для просмотра открытых дескрипторов или библиотек — Vies / Show Lower Panel.

Потоки в Process Explorer

Потоки отдельного процесса можно увидеть в программе Process Explorer. Для этого нужно дважды кликнуть по процессу и в открывшемся окне перейти на вкладку «Threads»:

Process Explorer (потоки процесса)

В колонках видна информация по каждому потоку:

  • TID — идентификатор потока.
  • CPU — загрузка процессора.
  • Cycles Delta — общее количество циклов процессора, которое этот процесс использовал с момента последнего обновления работы Process Explorer. Скорость обновления программы можно настроить, указав например 5 минут.
  • Suspend Count — количество приостановок потока.
  • Service — название службы.
  • Start Address — начальный адрес процедуры, который начинает выполнение нового потока. Выводится в формате:«модуль!функция».

При выделении потока, снизу показана следующую информация:

Изучение активности потока

  • Идентификатор потока.
  • Время начала работы потока.
  • Состояние потока.
  • Время выполнения в режиме ядра и в пользовательском режиме.
  • Счетчик переключения контекста для центрального процессора.
  • Количество циклов процессора.
  • Базовый приоритет.
  • Динамический приоритет (текущий).
  • Приоритет ввода / вывода.
  • Приоритет памяти.
  • Идеальный процессор (предпочтительный процессор).

Есть также кнопки:

Устройство Windows. Изучение активности потока, изображение №3

  • Stack — посмотреть стек процесса;
  • Module — посмотреть свойства запущенного исполняемого файла;
  • Permission — посмотреть права на поток;
  • Kill — завершить поток;
  • Suspend — приостановить поток.

Задания в Process Explorer

Process Explorer может выделить процессы, управляемые заданиями. Чтобы включить такое выделение откройте меню «Options» и выберите команду «Configure Colors», далее поставьте галочку «Jobs»:

Process Explorer — выделение заданий

Более того, страницы свойств таких процессов содержат дополнительную вкладку Job с информацией о самом объекте задания. Например приложение Skype работает со своими процессами как за заданием:

Process Explorer — вкладка Job

Запустите командную строку и введите команду:

>runas /user:<домен>\<пользователь> cmd

Таким образом вы запустите еще одну командную строку от имени этого пользователя. Служба Windows, которая выполняет команды runas, создает безымянное задание, чтобы во время выхода из системы завершить процессы из задания.

В новой командной строке запустите блокнот:

>notepad.exe

Далее запускаем Process Explorer и находим такое дерево процессов:

Устройство Windows. Задания, изображение №3

Как видим, процесс cmd и notepad это процессы связанные с каким-то заданием. Если дважды кликнуть по любому из этих процессов и перейти на вкладку Job, то мы увидим следующее:

Process Explorer — вкладка Job

Тут видно что эти два процесса работают в рамках одного задания.

Вернуться к оглавлению

Сводка

Процессы Windows

Имя статьи

Процессы Windows

Описание

Работа операционной системы Windows основана на работе процессов. В этой статье разберём что такое Windows процессы, их свойства, состояния и другое

С точки зрения
программирования каждый процесс win32/64
включает компоненты (рис. 22):

  • один или несколько
    потоков;

  • виртуальное
    адресное пространство, отличное от
    адресных пространств других процессов,
    за исключением случаев явного разделения
    памяти;

  • один или более
    сегментов кода, включая код DLL;

Рис. 22. Структура
процесса и его потоков

  • один
    или более сегментов данных, содержащих
    глобальные переменные;

  • строки окружения
    с информацией о переменных окружениях,
    таких как текущий путь поиска файла и
    др.;

  • память кучи
    процесса;

  • ресурсы процесса
    (открытые дескрипторы, файлы, другие
    кучи).

Атрибуты процесса
и потока в Windows
приведены в табл. 2.

Атрибуты процесса
и потока в Windows
Таблица 2

Процесс

Поток

Идентификатор процесса — уникальное
значение, идентифицирующее процесс
в ОС

Идентификатор потока — уникальное
значение, идентифицирующее поток,
когда он вызывает сервис.

Дескриптор защиты – описывает, кто
создал процесс, права доступа и пр.

Контекст потока – набор значений
регистров, которыми определяется
состояние выполняемого потока.

Базовый приоритет – базовый приоритет
для потоков

Динамический приоритет — приоритет
выполняемого потока в данный момент.

Базовый
приоритет – нижний приоритет
динамического приоритета потока.

Родственность процессов по умолчанию
– заданный по умолчанию набор процессов,
где возможно выполнение потоков.

Родственность процессов по потоку –
множество процессов, где возможно
выполнение потоков.

Время выполнения – суммарное время,
затраченное на выполнение всех потоков
в процессе.

Время выполнения потока — совокупное
время, затраченное на выполнение
потока в пользовательском режиме и
режиме ядра.

Счётчик ввода/вывода — переменные, в
которые заносятся сведения о количестве
и типе операций ввода/вывода, выполненных
потоками процесса.

Статус извещения (оповещения) – этот
флаг, который указывает, следует ли
потоку выполнять асинхронный вызов
процедуры.

Счётчик операций с виртуальной памятью
– это переменные, в которые заносятся
сведения о количестве и типе операций
с виртуальной памятью выполненных
потоками процесса.

Счётчик приостановок – в нём указывается,
сколько раз выполнение потока было
приостановлено без последующего
возобновления.

Квоты – максимальное количество
страничной памяти и процессорного
времени доступного процессу

Маркеры режима анонимного воплощения
– это временный признак доступа.

Порты исключения/отладки – это каналы
обмена информацией между процессами,
в которые диспетчер процессов должен
отправлять сообщения при возникновении
исключительных ситуаций одного из
потоков процесса.

Порт завершения – это канал обмена
информацией между процессами, куда
диспетчер процессов отправляет
сообщения при завершении потока.

Статус выхода –
причины завершения процесса

Статус выхода –
причины завершения потока

Все потоки процесса
совместно используют код, глобальные
переменные, строки окружения и ресурсы
процесса [3].
Каждый поток планируется независимо.
Поток включает следующие элементы:

  • стек вызова
    процедур, переменных, обработчиков
    исключений и автоматических данных;

  • локальная память
    потока – это массивы указателей, которые
    дают возможность процессу выделить
    память для создания собственного
    уникального окружения данных потока;

  • структура контекста,
    управляемая ядром, содержащая значение
    аппаратных регистров.

Некоторые атрибуты
потока подобны атрибутам процессов.
Значениия таких атрибутов потока
извлекаются из значений атрибутов
процесса. Например, в многопроцессорной
системе родственные процессоры по
потоку – это множество процессоров, на
которых может выполняться данный поток.
Оно совпадает с множеством процессоров
родственных по процессу или является
его подмножеством. Информация, содержащаяся
в контексте потока, позволяет ОС
приостанавливать и возобновлять потоки
[9].
Основные функции управления процессами
и потоками показаны в табл.3.

Сервисы процесса
и потока в Windows
Таблица 3

Процесс

Поток

Создание процесса CreateProcess().

Создание потока CreateThread().

Открытие процесса OpenProcess().

Открытие потока OpenThread()

Информация по запросу процесса

Информация по запросу потока

Информация по наладке процесса

Информация по наладке потока

Текущий процесс
GetCurrentProcessID()

Текущий поток GetCurrentThreadID()

Прекращение процесса
ExitProcess()

Завершение потока ExitThread()

Получение контекста

Установка контекста

Приостановка Delay()

Возобновление

Извещение потоков

Проверка извещения потока

Порт регистрации завершения.

Основной функцией
для управления процессом win32 является
функция CreateProcess(). Она создаёт процесс
с одним потоком. Так как процесс требует
наличие кода, то в вызове функции
CreateProcess() необходимо указывать имя
исполняемого файла программы. Функция
имеет 10 параметров и при успешном
выполнении возвращает дескрипторы для
процесса и для первичного потока.
Дополнительные потоки можно создать
функцией CreateThread(). Для Windows
все процессы одинаковы, и она не различает
дочерние и родительские, в отличие от
Unix.

Жизненный цикл
потока в Windows
(рис 23) проходит следующие шесть состояний
[3]:

Готовый к
выполнению: это поток, который может
быть направлен на выполнение, у него
есть все необходимые ресурсы кроме
процессорного времени. Диспетчер
микроядра отслеживает, все готовые
потоки и осуществляет их планирование
в соответствии с их приоритетом.

Резервный ‑
это поток, который будет запущен следующим
на данном процессоре. Поток находится
в этом состоянии до тех пор, пока процессор
не освободится. Если приоритет резервного
потока достаточно высок, то он может
вытеснить выполняющийся в данный момент
поток, иначе он ждёт, пока не произойдёт
блокировка выполняющегося потока или
пока не истечёт выделенный ему квант
времени.

Рис. 23. Жизненный
путь потока в Windows

Выполняющийся:
как только микроядро переключит поток,
резервный поток перейдёт в состояние
выполнения и будет в нём находится, пока
не произойдёт одно из событий: поток
будет вытеснен более приоритетным
потоком, если закончится квант времени,
будет блокирован или завершён.

Ожидающее:
поток входит в состояние ожидания, если
он блокирован каким-либо событием
(например, операцией ввода/вывода); он
добровольно ждёт синхронизации; среда
подсистемы предписывает потоку, чтобы
он сам себя остановил. После удовлетворения
условий ожидания, поток переходит в
состояние готовности, если все его
ресурсы доступны.

Переходное:
поток готов к выполнению, но не все
ресурсы необходимые ему для работы
доступны. При доступности всех ресурсов
он переходит в состояние готовности.

Завершающее:
завершение потока может быть инициировано
самим потоком, другим процессом или
может произойти вместе с завершением
родительского процесса.

После завершения
необходимых операций освобождения
ресурсов поток удаляется из операционной
системы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Управление процессами и потоками в Microsoft Windows


Download


Report


Transcript Управление процессами и потоками в Microsoft Windows

Управление процессами и
потоками в Microsoft Windows
Представление процессов
Диспетчеризация процессов и потоков
Планирование процессов и потоков
Характеристики процесса
Процесс как самостоятельная сущность
рассматривается на уровне архитектуры
ЭВМ и на уровне ОС.
На уровне архитектуры ЭВМ процесс
характеризуется:
- контекстом;
- адресным пространством.
На уровне ОС процесс описывается
специальной структурой уровня ядра – PCB
(Process Control Block)
Представление процесса в
защищенном режиме процессора Intel
Дескриптор TSS
активного процесса
TR
LDTR
CS
Селектор сегмента кода
LDT
Дескриптор сегмента кода
активного процесса
Дескриптор доп. сегмента
основной
Копия
дескриптора
TSS
TSS
Селектор
TSS
Сегмент
кода
Доп. сегмент
Доп. сегмент
сегменты кода,
данных, стека
GDTR
GDT
Оперативная память
Адресное пространство процесса в
защищенном режиме процессора Intel
Сегмент
Описание
Адресация
TSS
Task Status Segment –
сегмент состояния
задачи
Хранит полное
описание контекста
задачи
-Через
Сегмент
кода
Каждая задача
обязательно должна
иметь хотя бы один
сегмент кода
-Через
Другие
сегменты
Могут содержать код и
данные, в т.ч.
собственные стеки
процесса (задачи)
-Через
специальный системный
дескриптор, который хранится в
таблице GDT
-Селектор дескриптора и копия
самого дескриптора хранятся в
регистре TR
дескриптор в таблице LDT
-Селектор дескриптора всегда
хранится в регистре CS
дескрипторы в таблице LDT
-Селекторы дополнительных
сегментов хранятся в сегментных
регистрах DS, ES, FS, GS, SS
Контекст процесса в защищенном
режиме процессора Intel
-
Регистры общего назначения (EAX, EBX, ECX, EDX,
EDI, ESI, ESP, EBP);
Регистры состояния (EIP, EFLAGS);
Регистры состояния процессора (CR0-CR4);
Сегментные регистры (CS, DS, ES, FS, GS, SS);
Регистры управления памятью (LDTR, TR);
Значение поля селектора TSS из регистра TR для
процесса, который запустил данный процесс;
Содержимое таблицы LDT;
Содержимое каталогов и таблиц страниц;
Адрес битовой карты ввода/вывода.
Представление процесса на уровне ОС
В общем случае – информация о
процессе (контекст процесса) ОС
хранят в структурах PCB – Process
Control Block (блок управления
процессом)
Структура PCB и состав контекста
процесса различен для каждой
конкретной ОС
Представление процессов в ОС
Windows XP




Процесс – абстрактная
структура, определяющая
единое адресное
пространство и контекст
одного или нескольких
взаимосвязанных потоков
Поток – системный объект
операционной системы,
реально выполняющийся в
процессоре.
При создании любого
процесса всегда создается
первичный поток
Потоки могут порождать
новые потоки
Основной
поток
Порожденный
поток
Порожденный
поток
Процесс
Структуры Windows для управления
процессами и потоками (обобщенная
схема)
Структура EPROCESS
Блок процесса ядра (PCB)
Блок переменных окружения процесса
(PEB)
Структура ETHREAD
Структура KTHREAD
Блок переменных окружения потока
(TEB)
Уровни управления процессами
Аппаратный уровень
Реализуются примитивные операции по
управлению процессами:
-прерывания;
-переключение контекстов задач.
Диспетчеризация процессов
(уровень ядра)
Реализуются примитивы перевода процессов из
одного состояния в другое – запуск, приостановка,
возобновление, остановка (завершение)
Планирование процессов
(уровень менеджера
процессов)
Реализуется строгий и сложный алгоритм
управления состояниями процессов с учетом
различных факторов, условий функционирования
процессов, особенностей аппаратной части и
операционной системы
Механизмы управления процессами,
реализуемые аппаратно
Базовые аппаратные механизмы
Прерывания
Переключение задач
Все механизмы, реализуемые
аппаратно, в ОС Microsoft Windows
замаскированы уровнем HAL
Представление процесса на
аппаратном уровне (CPU Intel)
GDTR
Дескриптор TSS
активного процесса
TR
LDTR
CS
Селектор сегмента кода
LDT
Дескриптор сегмента кода
активного процесса
Дескриптор доп. сегмента
основной
TSS
Селектор
TSS
Сегмент
кода
Доп. сегмент
Доп. сегмент
сегменты кода,
данных, стека
Копия
дескриптора
TSS
Оперативная память
Реализация переключения задач в
защищенном режиме CPU Intel
 Для команд CALL и JMP проверяет привилегии (CPL текущей
задачи и RPL селектора новой задачи не могут быть больше,
чем DPL шлюза или TSS, на который передается управление).
 Проверяется дескриптор TSS (его бит присутствия и лимит).
 Проверяется, что новый TSS, старый TSS и все дескрипторы
сегментов находятся в страницах, отмеченных как
присутствующие.
 Сохраняется состояние задачи.
 Загружается регистр TR. Если на следующих шагах происходит
исключение, его обработчику придется доделывать
переключение задач, вместо того чтобы повторять ошибочную
команду.
 Тип новой задачи в дескрипторе изменяется на занятый и
устанавливается флаг TS в CR0.
 Загружается состояние задачи из нового TSS: LDTR, CR3,
EFLAGS, EIP, регистры общего назначения и сегментные
регистры.
Механизмы диспетчеризации
процессов уровня ядра Windows
Создание процесса
Создание потока
Приостановка процесса
Приостановка потока
Активизация процесса
Активизация потока
Завершение процесса
Завершение потока
Создание процесса в Windows и
функция CreateProcess
 Открытие файла-образа процесса (имя.exe или
имя.com)
 Создание объекта процесс исполнительной системы
(PCB)
 Создание первичного потока
 Уведомление о создании процесса и первичного
потока
 Начать выполнение первичного потока
 Инициализировать адресное пространство процесса
в контексте нового процесса и потока, подгрузить
динамические библиотеки (*.dll)
 Начать выполнение программы
Предварительные действия при
запуске процесса
 Перед запуском процесса CreateProcess проверяет параметр
CreationFlags, который указывается при запуске нового
процесса и задает приоритеты процесса. Если задано несколько
приоритетов, Windows выберет самый низкий из них
 Если приоритеты процесса не заданы, то Windows установит
приоритет Normal
 Если приоритет процесса-создателя Idle или Bellow Normal, а
приоритет нового процесса не указан, то Windows установит
приоритет нового процесса равный приоритету процесса
создателя
 Если создается процесс с приоритетом Real-Time, а создатель
не имеет привилегий на создание таких процессов и/или
привилегии Increase Scheduling Priority, то новый процесс будет
создан с приоритетом High, что ниже приоритета Real-Time
 Происходит сопоставление окна процесса с объектом «рабочий
стол»
Этап 1. Открытие файла-образа
 Поиск Windows-образа, который будет выполнять
указанный процесс, и создание объекта «раздел» для
последующего проецирования его на адресное
пространство нового процесса
 В качестве имени Windows-образа выбирается
первый параметр командной строки
 Проверка политики безопасности (не запрещает ли
она запуск данного процесса)
 Если запускается программа Windows, то она
используется напрямую
 Если запускается не-Windows приложение, то ОС
ищет специальный образ поддержки (support image)
для запуска данной программы
Этап 1. Открытие файла-образа
Этап 1. Открытие файла-образа:
завершение
 Запускаемый файл успешно открыт
 Для него создан объект «раздел», но этот
раздел еще не спроецирован в память
 Если в процессе открытия файла возникают
проблемы, то Windows находит в реестре
информацию об отладчике для данного типа
приложений и повторно запускает
CreateProcess
Этап 2. Создание объекта «процесс»
 Формируется блок EPROCESS
 Создается начальное адресное пространство
процесса
 Инициализируется блок процесса ядра (KPROCESS)
 Инициализируется адресное пространство процесса,
в т.ч. список рабочего набора и дескрипторы
виртуального адресного пространства
 Образ процесса проецируется на адресное
пространство
 Формируется блок PEB
 Завершается инициализация объекта «процесс»
исполнительной системы Windows
Этап 2а: Формирование блока
EPROCESS
 Создание блока EPROCESS
 От родительского процесса наследуется привязка к
процессорам
 Устанавливаются минимальное и максимальное значения
рабочего набора
 Настраивается блок квот нового процесса (устанавливается
ссылка на блок квот родительского процесса и увеличивается
счетчик ссылок последнего)
 Наследуется пространство имен устройств Windows
 Для нового процесса сохраняется идентификатор родительского
процесса
 Настраивается маркер доступа
 Наследуется от родителей
 Если используется функция CreateProcessAsUser создается новый
маркер
 Инициализируется таблица описателей
 Статус нового процесса заменяется на STATUS_PENDING
Этап 2b: создание начального
адресного пространства процесса
 В соответствующих таблицах страниц
формируются записи, позволяющие
подкачивать начальные страницы процесса
 Значение максимально доступного
количества резидентных страниц процесса
уменьшается на значение количества
страниц в рабочем наборе по умолчанию
 На адресное пространство проецируются
страницы таблицы страниц для
неподкачиваемого системного адресного
пространства и системного кэша
Этап 2c: создание блока процесса ядра
(KPROCESS)
 Инициализация блока KPROCESS
 Устанавливаются ссылки на блоки потоков ядра
(KTHREAD)
 Устанавливаются ссылки на таблицы страниц
процесса
 Инициализируются поля блока KPROCESS,
хранящие информацию о времени выполнения
процесса
 Устанавливается базовый приоритет процесса
 Устанавливается привязка процесса к процессорам
 Определяется базовое значение кванта времени для
данного процесса
Этап 2d: инициализация адресного
пространства процесса
 Диспетчер виртуальной памяти присваивает времени
последнего усечения рабочего набора процесса
текущее время
 Инициализируется список страниц рабочего набора
 Раздел проецируется на адресное пространство
процесса, и базовый адрес раздела процесса
приравнивается базовому адресу образа
 На адресное пространство процесса проецируется
ntdll.dll
 На адресное пространство процесса проецируются
таблицы NLS (National Language Support)
Этап 2е: инициализация блока PEB
Формируется блок PEB
Заполняются поля блока PEB
Этап 2f: завершение инициализации блока
«процесс» исполнительной системы
 Если разрешен аудит, то факт создания процесса
фиксируется в журнале безопасности
 Если родительский процесс входил в задание, то и новый
процесс включается в задание
 Если для процесса был указан флаг создания,
отмечающий, что данный процесс может выполняться
только в однопроцессорной системе, то для выполнения
всех потоков процесса выбирается один процессор
 Привязка процесса к процессору копируется в PEB и в
дальнейшем используется как привязка по умолчанию
 Блок процесса помещается в конец списка активных
процессов
 Устанавливается время создания процесса
 Возвращается дескриптор созданного процесса
Этап 3. Создание первичного потока
 К началу этого этапа процесс полностью
создан, но не может ничего делать, т.к. у него
нет ни одного потока
 Для создания потока необходимо создать
стек и контекст, в котором он будет
выполняться
 Первичный поток создается системным
вызовом NtCreateThread с параметром PEB
 Поток будет создан в приостановленном
состоянии и не будет ничего делать до
окончания инициализации процесса
Этап 3. Создание первичного потока:
NtCreateThread
Увеличивает счетчик потоков для данного процесса
Создает и инициализирует блок потока ETHREAD
Генерирует идентификатор нового потока
В пользовательском адресном пространстве
формируется TEB
 Стартовый адрес потока пользовательского режима
сохраняется в блоке ETHREAD




 Для Windows-потоков это адрес системной стартовой
функции потока в kernel32.dll
 Стартовый адрес, указанный пользователем, также
сохраняется в ETHREAD, но в другом месте, что позволяет
системной функции вызвать пользовательскую стартовую
функцию
Этап 3. Создание первичного потока:
NtCreateThread (продолжение)
Инициализируется блок KTHREAD, в
который заносятся параметры,
необходимые для диспетчеризации и
планирования потоков
Вызываются общесистемные функции
для уведомления о создании потока
Настраиваются маркеры доступа потока
Поток готов к выполнению
Этап 4. Уведомление подсистемы
Windows о новом процессе
 К данному моменту созданы и процесс, и его
первичный поток
 Kernel32.dll отправляет подсистеме Windows
уведомление:
Описатели процесса и потока
Флаги создания
Идентификатор родительского процесса
Флаг принадлежности процесса к Windowsприложениям
 Получив уведомление Windows должна
подготовиться к выполнению нового процесса
и потока
Этап 4. Уведомление подсистемы
Windows о новом процессе
 CreateProcess дублирует описатели процесса и
потока, в результате чего количество пользователей
процесса становится равным 2
 Устанавливается класс приоритета процесса
 Создается и инициализируется блок процесса Csrss
 Настраивается порт исключений процесса как общий
порт функций для подсистемы Windows. Таким
образом, она сможет получать сообщения о
возникновении исключений
 Если процесс в данный момент отлаживается, то в
качестве порта функций выбирается отладочный
порт
 Создается и инициализируется блок потока Csrss
Этап 4. Уведомление подсистемы
Windows о новом процессе
(продолжение)
 CreateProcess включает поток в список потоков
процесса
 Увеличивается счетчик процессов в данном сеансе
 Устанавливается уровень завершения процесса по
умолчанию 0х280
 Блок нового процесса включается в список
общесистемных процессов Windows
 Создается и инициализируется структура
W32PROCESS, индивидуальная для каждого
процесса и используемся той частью процесса,
которая выполняется в режиме ядра
 Выводится курсор в виде стрелки с песочными
часами – система ждет от процесса GUI-вызова
Этап 5. Запуск первичного потока
Для завершения инициализации
процесса необходимо возобновить его
первичный поток (который был создан,
как приостановленный), если при этом
не указан флаг CREATE_SUSPENDED
Этап 6. Инициализация в контексте
нового процесса
 Начинается выполнение первичного потока нового
процесса
 Происходит системный вызов KiThreadStartup,
который понижает уровень IRQL с DPC/dispatch до
APC
 Вызывается системная функция
PspUserThreadStartup, параметром которой являтся
стартовый адрес потока
 Функция PspUserThreadStartup проверяет, разрешена
ли в системе предвыборка и, если да, то производит
предвыборку страниц процесса, которые он запускал
в течении первых 10 сек при предыдущем запуске
 Затем функция PspUserThreadStartup ставит APC
пользовательского режима в очередь для запуска
процедуры инициализации потока
Этап 6. Инициализация в контексте
нового процесса (продолжение)
 Когда поток вернется в пользовательский режим, APC
будет доставлен
 После завершения PspUserThreadStartup
управление передается KiThreadStartup, которая
возвращается из режима ядра, доставляет APC,
инициализирует загрузчик, кучи, таблицы NLS,
массивы локальной памяти потока и структуры
критической секции
 Функция KiThreadStartup загружает необходимые dll и
вызывает их точки входа
 Управление возвращается диспетчеру APC
пользовательского режима
 Начинается выполнение образа в пользовательском
режиме
Создание потока в Windows и функция
CreateThread
 Создание стека пользовательского режима в
адресном пространстве процесса
 Инициализация аппаратного контекста потока
 Создать объект потока исполнительной
системы (в приостановленном состоянии)
 Уведомление Windows о создании нового
потока
 Вернуть порождающему процессу (потоку)
идентификатор и дескриптор (HANDLE)
созданного потока
 Начать выполнение потока
Планирование потоков в Windows
 Дисциплина планирования Windows реализована на
основе вытесняющего планирования
 В системе используются приоритеты
 Всегда первым вытесняется готовый к выполнению
поток, обладающий наибольшим приоритетом
 На выбор потоков к выполнению также влияет
привязка потоков (а точнее – процессов) к
процессору
 Для управления временем выполнения потока
используется система квантования времени
 Величина кванта не постоянна и зависит от
 Конфигурационных параметров системы
 Статуса процесса (активный или фоновый)
 Использованием объекта «задание»
Диспетчеризация на уровне ядра –
диспетчер ядра
 Диспетчеризация может быть вызвана одним
из следующих событий:
Поток готов к выполнению – только что создан или
вышел из состояния ожидания
Поток вышел из состояния Running (истек квант
времени или поток переходит в состояние ожидания)
Изменяется приоритет процесса из-за системного
вызова или самой Windows
Изменена привязка к процессорам, из-за чего
процесс не может больше выполняться на данном
процессоре
Уровни приоритета
Назначение приоритетов с точки
зрения WindowsAPI
 По приоритету
процесса
Real-time
High
Above normal
Normal
Bellow normal
Idle
 По относительному
приоритету потоков
в рамках процесса
Time-critical
Highest
Above normal
Normal
Bellow normal
Lowest
Idle
Связь между приоритетами
WindowsAPI и ядра Windows
Установка базового приоритета
процессов и потоков
 Базовый приоритет процесса устанавливается при
его создании (параметром CreationFlags функции
CreateProcess)
 Если базовый приоритет процесса не указан, то он
наследуются от родительского процесса (как
правило, он устанавливается в Normal)
 Базовый приоритет потока устанавливается в
соответствии с унаследованным приоритетом
процесса и собственным относительным
приоритетом
 Кроме базового приоритета, каждый поток имеет
текущий приоритет, на основании которого
принимаются все решения относительно
планирования потока
Состояния потоков в ОС
Windows 2000/XP
Состояния потоков в OC
Windows Server 2003
Для каждого уровня приоритетов –
своя очередь
База данных диспетчера ядра
32-битна маска
Бит устанавливается
в 1, если в
соответствующей
очереди есть поток
Квант
 Квант – интервал процессорного времени,
отводимый Windows для выполнения потока
 По истечении кванта Windows пытается передать
управление потоку с тем же приоритетом. Если
такого нет, очередной квант отводится тому же
потоку, что и выполнялся
 В Windows 2000/XP величина кванта по умолчанию
составляет 2 интервала таймера
 В Windows Server 2003 – 12 интервалов (увеличен,
чтобы минимизировать переключения контекста)
 Длительность интервала таймера определяется HAL,
а не ядром
Учет квантов
 Величина кванта для каждого процесса хранится в
блоке процесса ядра в виде количество_интервалов
*3
 Это значение кванта используется при запуске
потоков
 Во время выполнения потока величина кванта
уменьшается по таймеру, каждый раз на 3
 Если поток прерывается, квант выполнения потока
все равно уменьшается на 3 при каждом прерывании
таймера
 Для ожидающих потоков (WaitForSingleObject или
WaitForMultileObjects) величина кванта уменьшается
всегда, даже если они сразу получили доступ к
ожидаемому объекту (при этом квант уменьшается на
1)
Изменение величины кванта
 Пользователь может изменить величину
кванта, указав одно из двух значений –
короткий (2) или длинный (12) в оснастке
Performance Options
 Начиная с Windows NT 4.0 Workstation
система использует алгоритм динамического
изменения квантов для активных процессов
(со статусом выше Idle). Если хотя бы один
поток процесса использует активное окно, то
его квант времени увеличивается в 3 раза
 Управление квантами возможно через реестр
Windows
Сценарии планирования
Самостоятельное переключение
Вытеснение
Завершение кванта
Завершение потока
Самостоятельное переключение
Поток самостоятельно
переходит в состояние
ожидания
(WaitForSingleObject или
WaitForMultipleObjects)
Система
запускает первый
готовый поток с
наивысшим
приоритетом
Вытеснение
Поток с высоким приоритетом вышел
из состояния ожидания или
приоритет для данного потока
повысился
Поток вытесняется.
Причиной вытеснения
этого потока может быть
то, что его приоритет
понизился
Завершение кванта
При завершении кванта Windows может
понизить приоритет приостановленного
потока. Тогда она будет искать для
выполнения новый поток с приоритетом,
не ниже нового приоритета
приостановленного потока
Для данного потока
Windows не понизила
приоритет – он остался в
конце своей очереди
Динамическое повышение приоритета
 После завершения операций ввода-вывода
 По окончании ожидания на семафоре или
событии исполнительной системы
 По окончании операции ожидания потоками
активного процесса
 При пробуждении GUI-процессов в связи с
операциями с окнами
 Если поток, готовый к выполнению,
задерживается из-за нехватки процессорного
времени
Повышение приоритета после
завершения операций ввода-вывода
 Windows считает, что ожидавшие потоки имеют
больше шансов немедленно начать выполнение
 Потоки не получают неоправданных привилегий, т.к.
пока они ожидали их квант времени был уменьшен
на 1
 Величина приращения всегда зависит от устройства,
завершения ввода/вывода на котором ожидал поток
 Приоритет потока всегда повышается относительно
базового, а не текущего приоритета
 Приращение приоритета всегда применяется в
области динамических приоритетов
 Приоритет не может стать больше 15
Изменение приоритета после
завершения операций ввода-вывода
Повышение приоритета после завершения
ожидания на семафорах и событиях
Приоритет потока повышается на 1,
если он ожидал семафора или события
(функции WaitForSingleObject или
WaitForMultipleObjects), после
выполнения функций SetEvent,
PulseEvent, ReleaseSemaphore
Правила повышения приоритета
аналогичны рассмотренным ранее
Повышение приоритетов потоков активного
процесса после завершения ожидания
 Текущий приоритет потока в активном процессе
всегда повышается на величину PsPrioritySeparation,
если он завершил ожидание на объекте ядра
 Фактически PsPrioritySeparation – индекс в таблице
квантов и используется для выбора величины
квантов для потоков активного процесса
 Но в данном случае эта величина (величина кванта)
используется как величина изменения приоритета
 Используется для повышения отзывчивости
интерактивных приложений
Повышение приоритетов при пробуждении
GUI-процессов в связи с операциями с
окнами
Приоритет потоков, владеющих окнами,
повышается на 2 после их пробуждения
из-за активности системы управления
окнами
Используется для повышения
отзывчивости интерактивных
приложений
Повышение приоритетов при нехватке
процессорного времени
 Применяется при блокировке потоков с низким
приоритетом потоками с высокими приоритетами
(тупики)
 Диспетчер настройки баланса раз в 1 сек сканирует
очереди, чтобы обнаружить тупиковые ситуации
 При обнаружении блокированных потоков, которые в
свою очередь блокируют другие потоки, Windows
повышает их приоритет до 15
 В Windows 2000/XP квант времени таких потоков
удваивается
 В Windows Server 2003 квант времени для таких
потоков устанавливается равным 4
Планирование потоков в
многопроцессорных системах
 База данных диспетчера ядра включает в себя
несколько стеков очередей – по одной для каждого
процессора
 В БД включается маска активных процессоров,
позволяющая определить количество доступных
процессоров
 В системах с HyperThreading
 Количество логических процессоров не попадает под
лицензионные ограничения на количество поддерживаемых
процессоров
 При выборе логического процессора для запуска потока
система учитывает, на каком физическом процессоре он
реализуется
 Нагрузка на процессоры рассчитывается на основании
физической привязки логических процессоров
Планирование потоков в
многопроцессорных системах: привязка к
процессору
 Каждый поток имеет маску привязки к процессору
 Привязка к процессору наследуется от процесса,
запустившего поток
 Привязка потоков к процессору может быть изменена
с целью оптимизации производительности и
пропускной способности системы
 Привязка потока к процессору может быть изменена
индивидуально или для всех потоков процесса
 На выбор процессора для выполнения потока влияет
не только привязка, но и особенности создания
процесса (например, процесс может быть создан для
запуска только в однопроцессорных системах)
Выбор процессора для потока при
наличии простаивающих процессоров
 При наличии простаивающих процессоров Windows
пытается подключить поток к ним в следующем
порядке:
 Идеальный
 Предыдущий
 Текущий
 В Windows 2000 выбирается первый простаивающий
 В Windows XP и Windows Server 2003
 Анализируется маска привязки потока
 Если система с Hyperthreading и имеется простаивающий
физический процессор, то список доступных процессоров
сокращается для набора его логических
 Из полученного списка исключаются спящие процессоры
 Из списка выбирается процессор с наименьшим номером
Выбор процессора для потока при
отсутствии простаивающих процессоров
 Если на идеальном процессоре выполняется
поток с приоритетом меньше, чем у
запускаемого потока, то запускаемый поток
вытеснит выполняющийся поток со своего
идеального процессора
 Если при выборе процессора нельзя выбрать
идеальный (только в Windows 2000), то
выбирается процессор с наибольшим
номером
 После выбора процессора формируется
межпроцессорное прерывание
Задания
 Задание – объект ядра, обеспечивающий управление
одним или несколькими процессами, как группой
 Задание позволяет определить:
 Максимальное число процессов в группе
 Общий лимит на процессорное время (для всех процессов
задания) в пользовательском режиме
 Индивидуальные лимиты процессов на процессорное время
в пользовательском режиме
 Класс планирования задания (размер кванта для потоков
процессов, входящих в задание)
 Привязку к процессорам
 Приоритет всех процессов задания
 Максимальный и минимальный размеры рабочего набора
 Лимит на виртуальную память

В этой статье мы поговорим на такие темы, как процессы и потокидискрипторы процесса, поговорим о синзронизации потоков и затронем всеми любимый диспетчер задач windows.

На протяжении существования процесса его выполнение может быть многократно прервано и продолжено. Для того, чтобы возобновить выполнение процесса, необходимо восстановить состояние его операционной среды. Состояние операционной среды отображается состоянием регистров и программного счетчика, режимом работы процессора, указателями на открытые файлы, информацией о незавершенных операциях ввода-вывода, кодами ошибок выполняемых данным процессом системных вызовов и т.д. Эта информация называется контекстом процесса.

Для того чтобы ОС могла управлять процессами, она должна располагать всей необходимой для этого информацией. С этой целью на каждый процесс заводится дескриптор процесса.

Дескриптор – специальная информационная структура, которая заводится на каждый процесс (описатель задачи, блок управления задачей).

В общем случае дескриптор содержит следующую информацию:

  1. Идентификатор процесса.
  2. Тип (или класс) процесса, который определяет для супервизора некоторые правила предоставления ресурсов.
  3. Приоритет процесса.
  4. Переменную состояния, которая определяет, в каком состоянии находится процесс (готов к работе, в состоянии выполнения, ожидание устройства ввода-вывода и т.д.)
  5. Защищенную область памяти (или адрес такой зоны), в которой хранятся текущие значения регистров процессора, если процесс прерывается, не закончив работы. Эта информация называется контекстом задачи.
  6. Информацию о ресурсах, которыми процесс владеет и/или имеет право пользоваться (указатели на открытые файлы, информация о незавершенных операциях ввода/вывода и т.п.).
  7. Место (или его адрес) для организации общения с другими процессами.
  8. Параметры времени запуска (момент времени, когда процесс должен активизироваться, и периодичность этой процедуры).
  9. В случае отсутствия системы управления файлами – адрес задачи на диске в ее исходном состоянии и адрес на диске, куда она выгружается из оперативной памяти, если ее вытесняет другая.

Дескриптор процесса по сравнению с контекстом содержит более оперативную информацию, которая должна быть легко доступна подсистеме планирования процессов. Контекст процесса содержит менее актуальную информацию и используется операционной системой только после того, как принято решение о возобновлении прерванного процесса.

Дескрипторы, как правило, постоянно располагаются в оперативной памяти с целью ускорить работу супервизора, который организует их в списки (очереди) и отображает изменение состояния процесса перемещением соответствующего описателя из одного списка в другой.

Для каждого состояния (за исключением состояния выполнения для однопроцессорной системы) ОС ведет соответствующий список задач, находящийся в этом состоянии. Однако для состояния ожидания может быть не один список, а столько, сколько различных видов ресурсов могут вызывать состояние ожидания.

Например, состояний ожидания завершения операции ввода/вывода может быть столько, сколько устройств ввода/вывода содержится в системе.

Процессы и потоки

Чтобы поддерживать мультипрограммирование, ОС должна определить и оформить для себя те внутренне единицы работы, между которыми будет разделяться процессор и другие ресурсы компьютера. В настоящее время в большинстве ОС определены два типа единиц работы:

  • Процесс (более крупная единица работы).
  • Поток (нить или тред) – более мелкая единица работы, которую требует для своего выполнения процесс.
  • Когда говорят о процессах, то тем самым хотят отметить, что ОС поддерживает их обособленность: у каждого процесса имеется свое виртуальное адресное пространство, каждому процессу назначаются свои ресурсы – файлы, окна и др. Такая обособленность нужна для того, чтобы защитить один процесс от другого, поскольку они, совместно используя все ресурсы вычислительной системы, конкурируют друг с другом.

В общем случае процессы просто никак не связаны между собой и могут принадлежать даже различным пользователям, разделяющим одну вычислительную систему. Другими словами, в случае процессов ОС считает их совершенно несвязанными и независимыми. При этом именно ОС отвечает за конкуренцию между процессами по поводу ресурсов.

Для повышения быстродействия процессов есть возможность задействовать внутренний параллелизм в самих процессах.

Например, некоторые операции, выполняемые приложением, могут требовать для своего исполнения достаточно длительного использования ЦП. В этом случае при интерактивной работе с приложением пользователь вынужден долго ожидать завершения заказанной операции и не может управлять приложением до тех пор, пока операция не выполнится до самого конца. Такие ситуации встречаются достаточно часто, например, при обработке больших изображений в графических редакторах. Если же программные модули, исполняющие такие длительные операции, оформлять в виде самостоятельных «подпроцессов» (потоков), которые будут выполняться параллельно с другими «подпроцессами», то у пользователя появляется возможность параллельно выполнять несколько операций в рамках одного приложения (процесса).

Можно выделить следующие отличия потоков от процессов:

  • ОС для потоков не должна организовывать полноценную виртуальную машину.
  • Потоки не имеют своих собственных ресурсов, они развиваются в том же виртуальном адресном пространстве, могут пользоваться теми же файлами, виртуальными устройствами и иными ресурсами, что и данный процесс.
  • Единственное, что потокам необходимо иметь, — это процессорный ресурс. В однопроцессорной системе потоки разделяют между собой процессорное время так же, как это делают обычные процессы, а в многопроцессорной системе могут выполняться одновременно, если не встречают конкуренции из-за обращения к иным ресурсам.

Главное, что обеспечивает многопоточность, — это возможность параллельно выполнять несколько видов операций в одной прикладной программе. За счет чего реализуется эффективное использование ресурсов ЦП, а суммарное время выполнения задач становится меньше.

Например, если табличный процессор или текстовый процессор были разработаны с учетом возможностей многопоточной обработки, то пользователь может запросить пересчет своего рабочего листа или слияние нескольких документов и одновременно продолжать заполнять таблицу или открывать для редактирования следующий документ.

Диспетчер задач WINDOWS

В диспетчере задач отображаются сведения о программах и процессах, выполняемых на компьютере. Кроме того, там можно просмотреть наиболее часто используемые показатели быстродействия процессов.

Диспетчер задач служит для отображения ключевых показателей быстродействия компьютера. Для выполняемых программ можно просмотреть их состояние и завершить программы, переставшие отвечать на запросы. Имеется возможность просмотра активности выполняющихся процессов с использованием до 15 параметров, а также графиков и сведений об использовании ЦП и памяти.

Кроме того, если имеется подключение к сети, можно просматривать состояние сети и параметры ее работы. Если к компьютеру подключились несколько пользователей, можно увидеть их имена, какие задачи они выполняют, а также отправить им сообщение.

На вкладке Процессы отображаются сведения о выполняющихся на компьютере процессах: сведения об использовании ЦП и памяти, счетчике процессов и некоторые другие параметры:

На вкладке Быстродействие, отображаются сведения о счетчике дескрипторов и потоках, параметры памяти:

Потребность в синхронизации потоков возникает только в мультипрограммной ОС и связана с совместным использованием аппаратных и информационных ресурсов компьютера. Синхронизация необходима для исключения гонок (см. далее) и тупиков при обмене данными между потоками, разделении данных, при доступе к процессору и устройствам ввода-вывода.

Синхронизация потоков и процессов заключается в согласовании их скоростей путем приостановки потока до наступления некоторого события и последующей его активизации при наступлении этого события.

Пренебрежение вопросами синхронизации в многопоточной системе может привести к неправильному решению задачи или даже к краху системы.

Пример. Задача ведения базы данных клиентов некоторого предприятия.

Каждому клиенту отводится отдельная запись в базе данных, в которой имеются поля Заказ и Оплата. Программа, ведущая базу данных, оформлена как единый процесс, имеющий несколько потоков, в том числе:

  • Поток А, который заносит в базу данных информацию о заказах, поступивших от клиентов.
  • Поток В, который фиксирует в базе данных сведения об оплате клиентами выставленных счетов.

Оба эти потока совместно работают над общим файлом базы данных, используя однотипные алгоритмы:

  1. Считать из файла БД в буфер запись и клиенте с заданным идентификатором.
  2. Ввести новое значение в поле Заказ (для потока А) или оплата (для потока В).
  3. Вернуть модифицированную запись в файл БД.

Обозначим шаги 1-3 для потока А как А1-А3, а для потока В как В1-В3. Предположим, что в некоторый момент поток А обновляет поле Заказ записи о клиенте N. Для этого он считывает эту запись в свой буфер (шаг А1), модифицирует значение поля Заказ (шаг А2), но внести запись в базу данных не успевает, так как его выполнение прерывается, например, вследствие истечение кванта времени.

Предположим, что потоку В также потребовалось внести сведения об оплате относительно того же клиента N. Когда подходит очередь потока В, он успевает считать запись в свой буфер (шаг В1) и выполнить обновление поля Оплата (шаг В2), а затем прерывается. Заметим, что в буфере у потока В находится запись о клиенте N, в которой поле Заказ имеет прежнее, не измененное значение.

Важным понятием синхронизации процессов является понятие «критическая секция» программы. Критическая секция — это часть программы, в которой осуществляется доступ к разделяемым данным. Чтобы исключить эффект гонок по отношению к некоторому ресурсу, необходимо обеспечить, чтобы в каждый момент в критической секции, связанной с этим ресурсом, находился максимум один процесс. Этот прием называют взаимным исключением.

Простейший способ обеспечить взаимное исключение — позволить процессу, находящемуся в критической секции, запрещать все прерывания. Однако этот способ непригоден, так как опасно доверять управление системой пользовательскому процессу; он может надолго занять процессор, а при крахе процесса в критической области крах потерпит вся система, потому что прерывания никогда не будут разрешены.

Другим способом является использование блокирующих переменных. С каждым разделяемым ресурсом связывается двоичная переменная, которая принимает значение 1, если ресурс свободен (то есть ни один процесс не находится в данный момент в критической секции, связанной с данным процессом), и значение 0, если ресурс занят. На рисунке ниже показан фрагмент алгоритма процесса, использующего для реализации взаимного исключения доступа к разделяемому ресурсу D блокирующую переменную F(D). Перед входом в критическую секцию процесс проверяет, свободен ли ресурс D. Если он занят, то проверка циклически повторяется, если свободен, то значение переменной F(D) устанавливается в 0, и процесс входит в критическую секцию. После того, как процесс выполнит все действия с разделяемым ресурсом D, значение переменной F(D) снова устанавливается равным 1.

Если все процессы написаны с использованием вышеописанных соглашений, то взаимное исключение гарантируется. Следует заметить, что операция проверки и установки блокирующей переменной должна быть неделимой. Поясняется это следующим образом. Пусть в результате проверки переменной процесс определил, что ресурс свободен, но сразу после этого, не успев установить переменную в 0, был прерван. За время его приостановки другой процесс занял ресурс, вошел в свою критическую секцию, но также был прерван, не завершив работы с разделяемым ресурсом. Когда управление было возвращено первому процессу, он, считая ресурс свободным, установил признак занятости и начал выполнять свою критическую секцию. Таким образом, был нарушен принцип взаимного исключения, что потенциально может привести к нежелаемым последствиям. Во избежание таких ситуаций в системе команд машины желательно иметь единую команду «проверка-установка», или же реализовывать системными средствами соответствующие программные примитивы, которые бы запрещали прерывания на протяжении всей операции проверки и установки.

Реализация критических секций с использованием блокирующих переменных имеет существенный недостаток: в течение времени, когда один процесс находится в критической секции, другой процесс, которому требуется тот же ресурс, будет выполнять рутинные действия по опросу блокирующей переменной, бесполезно тратя процессорное время. Для устранения таких ситуаций может быть использован так называемый аппарат событий. С помощью этого средства могут решаться не только проблемы взаимного исключения, но и более общие задачи синхронизации процессов. В разных операционных системах аппарат событий реализуется по-своему, но в любом случае используются системные функции аналогичного назначения, которые условно называются WAIT(x) и POST(x), где x — идентификатор некоторого события.

Если ресурс занят, то процесс не выполняет циклический опрос, а вызывает системную функцию WAIT(D), здесь D обозначает событие, заключающееся в освобождении ресурса D. Функция WAIT(D) переводит активный процесс в состояние ОЖИДАНИЕ и делает отметку в его дескрипторе о том, что процесс ожидает события D. Процесс, который в это время использует ресурс D, после выхода из критической секции выполняет системную функцию POST(D), в результате чего операционная система просматривает очередь ожидающих процессов и переводит процесс, ожидающий события D, в состояние ГОТОВНОСТЬ.

Обобщающее средство синхронизации процессов предложил Дейкстра, который ввел два новых примитива. В абстрактной форме эти примитивы, обозначаемые P и V, оперируют над целыми неотрицательными переменными, называемыми семафорами. Пусть S такой семафор. Операции определяются следующим образом:

V(S): переменная S увеличивается на 1 одним неделимым действием; выборка, инкремент и запоминание не могут быть прерваны, и к S нет доступа другим процессам во время выполнения этой операции.

P(S): уменьшение S на 1, если это возможно. Если S=0, то невозможно уменьшить S и остаться в области целых неотрицательных значений, в этом случае процесс, вызывающий P-операцию, ждет, пока это уменьшение станет возможным. Успешная проверка и уменьшение также является неделимой операцией.

В частном случае, когда семафор S может принимать только значения 0 и 1, он превращается в блокирующую переменную. Операция P заключает в себе потенциальную возможность перехода процесса, который ее выполняет, в состояние ожидания, в то время как V-операция может при некоторых обстоятельствах активизировать другой процесс, приостановленный операцией P.

Взаимоблокировка процессов

При организации параллельного выполнения нескольких процессов одной из главных функций ОС является корректное распределение ресурсов между выполняющимися процессами и  обеспечение процессов средствами взаимной синхронизации и обмена данными.

При параллельном исполнении процессов могут возникать ситуации, при которых два или более процесса все время находятся в заблокированном состоянии. Самый простой случай – когда каждый из двух процессов ожидает ресурс, занятый другим процессом. Из-за такого ожидания ни один из процессов не может продолжить исполнение и освободить в конечном итоге ресурс, необходимый другому процессу. Эта тупиковая ситуация называется дедлоком (dead lock), тупикомклинчем или взаимоблокировкой.

Говорят, что в мультизадачной системе процесс находится в состоянии тупика, если он ждет события, которое никогда не произойдет.

Тупиковые ситуации надо отличать от простых очередей, хотя и те и другие возникают при совместном использовании ресурсов и внешне выглядят похоже: процесс приостанавливается и ждет освобождения ресурса. Однако очередь — это нормальное явление, неотъемлемый признак высокого коэффициента использования ресурсов при случайном поступлении запросов. Она возникает тогда, когда ресурс недоступен в данный момент, но через некоторое время он освобождается, и процесс продолжает свое выполнение. Тупик же является в некотором роде неразрешимой ситуацией.

Проблема тупиков включает в себя следующие задачи:

  1. предотвращение тупиков.
  2. распознавание тупиков.
  3. восстановление системы после тупиков.

Тупики могут быть предотвращены на стадии написания программ, то есть программы должны быть написаны таким образом, чтобы тупик не мог возникнуть ни при каком соотношении взаимных скоростей процессов. Так, если бы в предыдущем примере процесс А и процесс В запрашивали ресурсы в одинаковой последовательности, то тупик был бы в принципе невозможен. Второй подход к предотвращению тупиков называется динамическим и заключается в использовании определенных правил при назначении ресурсов процессам, например, ресурсы могут выделяться в определенной последовательности, общей для всех процессов.

В некоторых случаях, когда тупиковая ситуация образована многими процессами, использующими много ресурсов, распознавание тупика является нетривиальной задачей. Существуют формальные, программно-реализованные методы распознавания тупиков, основанные на ведении таблиц распределения ресурсов и таблиц запросов к занятым ресурсам. Анализ этих таблиц позволяет обнаружить взаимные блокировки.

Если же тупиковая ситуация возникла, то не обязательно снимать с выполнения все заблокированные процессы. Можно снять только часть из них, при этом освобождаются ресурсы, ожидаемые остальными процессами, можно вернуть некоторые процессы в область свопинга, можно совершить «откат» некоторых процессов до так называемой контрольной точки, в которой запоминается вся информация, необходимая для восстановления выполнения программы с данного места. Контрольные точки расставляются в программе в местах, после которых возможно возникновение тупика.

Ниже представлена не простая расшифровка доклада с семинара CLRium, а переработанная версия для книги .NET Platform Architecture. Той её части, что относится к потокам.

Потоки и планирование потоков

Что такое поток? Давайте дадим краткое определение. По своей сути поток это:

  • Средство параллельного относительно других потоков исполнения кода;
  • Имеющего общий доступ ко всем ресурсам процесса.

Очень часто часто слышишь такое мнение, что потоки в .NET — они какие-то абсолютно свои. И наши .NET потоки являются чем-то более облегчённым чем есть в Windows. Но на самом деле потоки в .NET являются самыми обычными потоками Windows (хоть Windows thread id и скрыто так, что сложно достать). И если Вас удивляет, почему я буду рассказывать не-.NET вещи в хабе .NET, скажу вам так: если нет понимания этого уровня, можно забыть о хорошем понимании того, как и почему именно так работает код. Почему мы должны ставить volatile, использовать Interlocked и SpinWait. Дальше обычного lock дело не уйдёт. И очень даже зря.

Давайте посмотрим из чего они состоят и как они рождаются. По сути поток — это средство эмуляции параллельного исполнения относительно других потоков. Почему эмуляция? Потому, что поток как бы странно и смело это ни звучало — это чисто программная вещь, которая идёт из операционной системы. А операционная система создаёт этот слой эмуляции для нас. Процессор при этом о потоках ничего не знает вообще.

Задача процессора — просто исполнять код. Поэтому с точки зрения процессора есть только один поток: последовательное исполнение команд. А задача операционной системы каким-либо образом менять поток т.о. чтобы эмулировать несколько потоков.

Поток в физическом понимании

«Но как же так?», — скажите вы, — «во многих магазинах и на различных сайтах я вижу запись «Intel Xeon 8 ядер 16 потоков». Говоря по-правде это — либо скудность в терминологии либо — чисто маркетинговый ход. На самом деле внутри одного большого процессора есть в данном случае 8 ядер и каждое ядро состоит из двух логических процессоров. Такое доступно при наличии в процессоре технологии Hyper-Threading, когда каждое ядро эмулирует поведение двух процессоров (но не потоков). Делается это для повышения производительности, да. Но по большому счёту если нет понимания, на каких потоках идут расчёты, можно получить очень не приятный сценарий, когда код выполняется со скоростью, ниже чем если бы расчёты шли на одном ядре. Именно поэтому раздача ядер идёт +=2 в случае Hyper-Threading. Т.е. пропуская парные ядра.

Технология эта — достаточно спорная: если вы работаете на двух таких псевдо-ядрах (логических процессорах, которые эмулируются технологией Hyper-Threading), которые при этом находятся на одном физическом ядре и работают с одной и той-же памятью, то вы будете постоянно попадать в ситуацию, когда второй логический процессор так же пытается обратиться к данной памяти, создавая блокировку либо попадая в блокировку, т.к. поток, находящийся на первом ядре работает с той же памятью.

Возникает блокировка совместного доступа: хоть и идёт эмуляция двух ядер, на самом-то деле оно одно. Поэтому в наихудшем сценарии эти потоки исполняются по очереди, а не параллельно.

Так если процессор ничего не знает о потоках, как же достигается параллельное исполнение потоков на каждом из его ядер? Как было сказано, поток — средство операционной системы выполнять на одном процессоре несколько задач одновременно. Достигается параллелизм очень быстрым переключением между потоками в течение очень короткого промежутка времени. Последовательно запуская на выполнение код каждого из потоков и делая это достаточно часто, операционная система достигает цели: делает их исполнение псевдопараллельным, но параллельным с точки зрения восприятия человека. Второе обоснование существования потоков — это утверждение, что программа не так часто срывается в математические расчёты. Чаще всего она взаимодействует с окружающим её миром: различным оборудованием. Это и работа с жёстким диском и вывод на экран и работа с клавиатурой и мышью. Поэтому чтобы процессор не простаивал, пока оборудование сделает то, чего хочет от него программа, поток можно на это время установить в состояние блокировки: ожидания сигнала от операционной системы, что оборудование сделало то, что от него просили. Простейший пример этого — вызов метода Console.ReadKey().

Если заглянуть в диспетчер задач Windows 10, то можно заметить, что в данный момент в вашей системе существует около 1,5 тысячи потоков. И если учесть, что квант на десктопе равен 20 мс, а ядер, например, 4, то можно сделать вывод, что каждый поток получает 20 мс работы 1 раз в 7,5 сек… Ну конечно же, нет. Просто почти все потоки чего-то ждут. То ввода пользователя, то изменения ключей реестра… В операционной системе существует очень много причин, чтобы что-либо ждать.

Так что пока одни потоки в блокировке, другие — что-то делают.

Создание потоков

Простейшая функция создания потоков в пользовательском режиме операционной системы — CreateThread. Эта функция создаёт поток в текущем процессе. Вариантов параметризации CreateThread очень много и когда мы вызываем new Thread(), то из нашего .NET кода вызывается данная функция операционной системы.

В эту функцию передаются следующие атрибуты:

1) Необязательная структура с атрибутами безопасности:

  • Дескриптор безопасности (SECURITY_ATTRIBUTES) + признак наследуемости дескриптора.

    В .NET его нет, но можно создать поток через вызов функции операционной системы;

2) Необязательный размер стека:

  • Начальный размер стека, в байтах (система округляет это значение до размера страницы памяти)

    Т.к. за нас размер стека передаёт .NET, нам это делать не нужно. Это необходимо для вызовов методов и поддержки памяти.

3) Указатель на функцию — точка входа нового потоками
4) Необязательный аргумент для передачи данных функции потока.

Из того, что мы не имеем в .NET явно — это структура безопасности с атрибутами безопасности и размер стэка. Размер стэка нас мало интересует, но атрибуты безопасности нас могут заинтересовать, т.к. сталкиваемся мы с ними впервые. Сейчас мы рассмотривать их не будем. Скажу только, что они влияют на возможность изменения информации о потоке средствами операционной системы.

Если мы создаём любым способом: из .NET или же вручную, средствами ОС, мы как итог имеем и ManageThreadId и экземпляр класса Thread.

Также у этой функции есть необязательный флаг: CREATE_SUSPENDED — поток после создания не стартует. Для .NET это поведение по умолчанию.

Помимо всего прочего существует дополнительный метод CreateRemoteThread, который создаёт поток в чужом процессе. Он часто используется для мониторинга состояния чужого процесса (например программа Snoop). Этот метод создаёт в другом процессе поток и там наш поток начинает исполнение. Приложения .NET так же могут заливать свои потоки в чужие процессы, однако тут могут возникнуть проблемы. Первая и самая главная — это отсутствие в целевом потоке .NET runtime. Это значит, что ни одного метод фреймворка там не будет: только WinAPI и то, что вы написали сами. Однако, если там .NET есть, то возникает вторая проблема (которой не было раньше). Это — версия runtime. Необходимо: понять, что там запущено (для этого необходимо импортировать не-.NET методы runtime, которые написаны на C/C++ и разобраться, с чем мы имеем дело). На основании полученной информации подгрузить необходимые версии наших .NET библиотек и каким-то образом передать им управление.

Я бы рекомендовал вам поиграться с задачкой такого рода: вжиться в код любого .NET процесса и вывести куда-либо сообщение об удаче внедрения (например, в файл лога)

Планирование потоков

Для того чтобы понимать, в каком порядке исполнять код различных потоков, необходима организация планирования тих потоков. Ведь система может иметь как одно ядро, так и несколько. Как иметь эмуляцию двух ядер на одном так и не иметь такой эмуляции. На каждом из ядер: железных или же эмулированных необходимо исполнять как один поток, так и несколько. В конце концов система может работать в режиме виртуализации: в облаке, в виртуальной машине, песочнице в рамках другой операционной системы. Поэтому мы в обязательном порядке рассмотрим планирование потоков Windows. Это — настолько важная часть материала по многопоточке, что без его понимания многопоточка не встанет на своё место в нашей голове никоим образом.

Итак, начнём. Организация планирования в операционной системе Windows является: гибридной. С одной стороны моделируются условия вытесняющей многозадачности, когда операционная система сама решает, когда и на основе каких условия вытеснить потоки. С другой стороны — кооперативной многозадачности, когда потоки сами решают, когда они всё сделали и можно переключаться на следующий (UMS планировщик). Режим вытесняющей многозадачности является приоритетным, т.к. решает, что будет исполняться на основе приоритетов. Почему так? Потому что у каждого потока есть свой приоритет и операционная система планирует к исполнению более приоритетные потоки. А вытесняющей потому, что если возникает более приоритетный поток, он вытесняет тот, который сейчас исполнялся. Однако во многих случаях это бы означало, что часть потоков никогда не доберется до исполнения. Поэтому в операционной системе есть много механик, позволяющих потокам, которым необходимо время на исполнение его получить несмотря на свой более низкий по сравнению с остальными, приоритет.

Уровни приоритета

Windows имеет 32 уровня приоритета (0-31)

  • 1 уровень (00 — 00) — это Zero Page Thread;
  • 15 уровней (01 — 15) — обычные динамические приоритеты;
  • 16 уровней (16 — 31) — реального времени.

Самый низкий приоритет имеет Zero Page Thread. Это — специальный поток операционной системы, который обнуляет страницы оперативной памяти, вычищая тем самым данные, которые там находились, но более не нужны, т.к. страница была освобождена. Необходимо это по одной простой причине: когда приложение освобождает память, оно может ненароком отдать кому-то чувствительные данные. Личные данные, пароли, что-то ещё. Поэтому как операционная система так и runtime языков программирования (а у нас — .NET CLR) обнуляют получаемые участки памяти. Если операционная система понимает, что заняться особо нечем: потоки либо стоят в блокировке в ожидании чего-либо либо нет потоков, которые исполняются, то она запускает самый низко приоритетный поток: поток обнуления памяти. Если она не доберется этим потоком до каких-либо участков, не страшно: их обнулят по требованию. Когда их запросят. Но если есть время, почему бы это не сделать заранее?

Продолжая говорить о том, что к нам не относится, стоит отметить приоритеты реального времени, которые когда-то давным-давно таковыми являлись, но быстро потеряли свой статус приоритетов реального времени и от этого статуса осталось лишь название. Другими словами, Real Time приоритеты на самом деле не являются таковыми. Они являются приоритетами с исключительно высоким значением приоритета. Т.е. если операционная система будет по какой-то причине повышать приоритет потока с приоритетом из динамической группы (об этом — позже, но, например, потому, что потоку освободили блокировку) и при этом значение до повышения было равно 15, то повысить приоритет операционная система не сможет: следующее значение равно 16, а оно — из диапазона реального времени. Туда повышать такими вот «твиками» нельзя.

Уровень приоритетов процессов с позиции Windows API.

Приоритеты — штука относительная. И чтобы нам всем было проще в них ориентироваться, были введены некие правила относительности расчетов: во-первых все потоки вообще (от всех приложений) равны для планировщика: планировщик не различает потоки это различных приложений или же одного и того же приложения. Далее, когда программист пишет свою программу, он задаёт приоритет для различных потоков, создавая тем самым модель многопоточности внутри своего приложения. Он прекрасно знает, почему там был выбран пониженный приоритет, а тут — обычный. Внутри приложения всё настроено. Далее, поскольку есть пользователь системы, он также может выстраивать приоритеты для приложений, которые запускаются на этой системе. Например, он может выбрать повышенный приоритет для какого-то расчетного сервиса, отдавая ему тем самым максимум ресурсов. Т.е. уровень приоритета можно задать и у процесса.

Однако, изменение уровня приоритета процесса не меняет относительных приоритетов внутри приложения: их значения сдвигаются, но не меняется внутренняя модель приоритетов: внутри по-прежнему будет поток с пониженным приоритетом и поток — с обычным. Так, как этого хотел разработчик приложения. Как же это работает?

Существует 6 классов приоритетов процессов. Класс приоритетов процессов — это то, относительно чего будут создаваться приоритеты потоков. Все эти классы приоритетов можно увидеть в «Диспетчере задач», при изменении приоритета какого-либо процесса.

Другими словами класс приоритета — это то, относительно чего будут задаваться приоритеты потоков внутри приложения. Чтобы задать точку отсчёта, было введено понятие базового приоритета. Базовый приоритет — это то значение, чем будет являться приоритет потока с типом приоритета Normal:

  • Если процесс создаётся с классом Normal и внутри этого процесса создаётся поток с приоритетом Normal, то его реальный приоритет Normal будет равен 8 (строка №4 в таблице);
  • Если Вы создаёте процесс и у него класс приоритета Above Normal, то базовый приоритет будет равен 10. Это значит, что потоки внутри этого процесса будут создаваться с более повышенным приоритетом: Normal будет равен 10.

Для чего это необходимо? Вы как программисты знаете модель многопоточности, которая у вас присутствует.
Потоков может быть много и вы решаете, что один поток должен быть фоновым, так как он производит вычисления и вам
не столь важно, когда данные станут доступны: важно чтобы поток завершил вычисления (например поток обхода и анализа дерева). Поэтому, вы устанавливаете пониженный приоритет данного потока. Аналогично может сложится ситуация когда необходимо запустить поток с повышенным приоритетом.

Представим, что ваше приложение запускает пользователь и он решает, что ваше приложение потребляет слишком много процессорных ресурсов. Пользователь считает, что ваше приложение не столь важное в системе, как какие-нибудь другие приложения и понижает приоритет вашего приложения до Below Normal. Это означает, что он задаёт базовый приоритет 6 относительно которого будут рассчитываться приоритеты потоков внутри вашего приложения. Но в системе общий приоритет упадёт. Как при этом меняются приоритеты потоков внутри приложения?

Таблица 3

Normal остаётся на уровне +0 относительно уровня базового приоритета процесса. Below normal — это (-1) относительно уровня базового. Т.е. в нашем примере с понижением уровня приоритета процесса до класса Below Normal приоритет потока ‘Below Normal’ пересчитается и будет не 8 - 1 = 7 (каким он был при классе Normal), а 6 - 1 = 5. Lowest (-2) станет равным 4.

Idle и Time Critical — это уровни насыщения (-15 и +15). Почему Normal — это 0 и относительно него всего два шага: -2, -1, +1 и +2? Легко провести параллель с обучением. Мы ходим в школу, получаем оценки наших знаний (5,4,3,2,1) и нам понятно, что это за оценки: 5 — молодец, 4 — хорошо, 3 — вообще не постарался, 2 — это не делал ни чего, а 1 — это то, что можно исправить потом на 4. Но если у нас вводится 10-ти бальная система оценок (или что вообще ужас — 100-бальная), то возникает неясность: что такое 9 баллов или 7? Как понять, что вам поставили 3 или 4?

Тоже самое и с приоритетами. У нас есть Normal. Дальше, относительно Normal у нас есть чуть повыше
Normal (Normal above), чуть пониже Normal (Normal below). Также есть шаг на два вверх
или на два вниз (Higest и Lowest). Нам, поверьте, нет никакой необходимости в более подробной градации. Единственное, очень редко, может раз в жизни, нам понадобится сказать: выше чем любой приоритет в системе. Тогда мы выставляем уровень Time Critical. Либо наоборот: это надо делать, когда во всей системе делать нечего. Тогда мы выставляем уровень Idle. Это значения — так называемые уровни насыщения.

Как рассчитываются уровни приоритета?

У нас бал класс приоритета процесса Normal (Таблица 3) и приоритет потоков Normal — это 8. Если процесс Above Normal то поток Normal получается равен 9. Если же процесс выставлен в Higest, то поток Normal получается равен 10.

Поскольку для планировщика потоков Windows все потоки процессов равнозначны, то:

  • Для процесса класса Normal и потока Above-Normal
  • Для процесса класса Higest и потока Normal
    конечные приоритеты будут одинаковыми и равны 10.

Если мы имеем два процесса: один с приоритетом Normal, а второй — с приоритетом Higest, но при этом
первый имел поток Higest а второй Normal, то система их приоритеты будет рассматривать как одинаковые.

Как уже обсуждалось, группа приоритетов Real-Time на самом деле не является таковой, поскольку настоящий Real-Time — это гарантированная доставка сообщения за определённое время либо обработка его получения. Т.е., другими словами, если на конкретном ядре есть такой поток, других там быть не должно. Однако это ведь не так: система может решить, что низко приоритетный поток давно не работал и дать ему время, отключив real-time. Вернее его назвать классом приоритетов который работает над обычными приоритетами и куда обычные приоритеты не могут уйти, попав под ситуации, когда Windows временно повышает им приоритет.

Но так как поток повышенным приоритетом исполняется только один на группе ядер, то получается,
что если у вас даже Real-Time потоки, не факт, что им будет выделено время.

Если перевести в графический вид, то можно заметить, что классы приоритетов пересекаются. Например, существует пересечение Above-Normal Normal Below-Normal (столбик с квадратиками):

Это значит, что для этих трех классов приоритетов процессов существуют такие приоритеты потоков внутри этих классов, что реальный приоритет будет равен. При этом, когда вы задаёте приоритет процессу вы просто повышаете или понижаете все его внутренние приоритеты потоков на определённое значение (см. Таблица 3).

Поэтому, когда процессу выдаётся более высокий класс приоритета, это повышает приоритет потоков процесса относительно обычных – с классом Normal.

Кстати говоря, мы стартовали продажи на CLRium #7, в котором мы с огромным удовольствием будем говорить про практику работы с многопоточным кодом. Будут и домашние задания и даже возможность работы с личным ментором.

Загляните к нам на сайт: мы сильно постарались, чтобы его было интересно изучить.

  • Уровень резервной батареи windows 10 что это
  • Управление пространством диска windows 10
  • Управление устройствами bluetooth windows 10
  • Уровень заряда батареи ноутбука windows 10
  • Управление глазами windows 10 что это