Процессы и потоки, диспетчер задач windows, синхронизация потоков.
В этой статье мы поговорим на такие темы, как процессы и потоки, дискрипторы процесса, поговорим о синзронизации потоков и затронем всеми любимый диспетчер задач windows.
На протяжении существования процесса его выполнение может быть многократно прервано и продолжено. Для того, чтобы возобновить выполнение процесса, необходимо восстановить состояние его операционной среды. Состояние операционной среды отображается состоянием регистров и программного счетчика, режимом работы процессора, указателями на открытые файлы, информацией о незавершенных операциях ввода-вывода, кодами ошибок выполняемых данным процессом системных вызовов и т.д. Эта информация называется контекстом процесса.
Для того чтобы ОС могла управлять процессами, она должна располагать всей необходимой для этого информацией. С этой целью на каждый процесс заводится дескриптор процесса.
Дескриптор – специальная информационная структура, которая заводится на каждый процесс (описатель задачи, блок управления задачей).
В общем случае дескриптор содержит следующую информацию:
- Идентификатор процесса.
- Тип (или класс) процесса, который определяет для супервизора некоторые правила предоставления ресурсов.
- Приоритет процесса.
- Переменную состояния, которая определяет, в каком состоянии находится процесс (готов к работе, в состоянии выполнения, ожидание устройства ввода-вывода и т.д.)
- Защищенную область памяти (или адрес такой зоны), в которой хранятся текущие значения регистров процессора, если процесс прерывается, не закончив работы. Эта информация называется контекстом задачи.
- Информацию о ресурсах, которыми процесс владеет и/или имеет право пользоваться (указатели на открытые файлы, информация о незавершенных операциях ввода/вывода и т.п.).
- Место (или его адрес) для организации общения с другими процессами.
- Параметры времени запуска (момент времени, когда процесс должен активизироваться, и периодичность этой процедуры).
- В случае отсутствия системы управления файлами – адрес задачи на диске в ее исходном состоянии и адрес на диске, куда она выгружается из оперативной памяти, если ее вытесняет другая.
Дескриптор процесса по сравнению с контекстом содержит более оперативную информацию, которая должна быть легко доступна подсистеме планирования процессов. Контекст процесса содержит менее актуальную информацию и используется операционной системой только после того, как принято решение о возобновлении прерванного процесса.
Дескрипторы, как правило, постоянно располагаются в оперативной памяти с целью ускорить работу супервизора, который организует их в списки (очереди) и отображает изменение состояния процесса перемещением соответствующего описателя из одного списка в другой.
Для каждого состояния (за исключением состояния выполнения для однопроцессорной системы) ОС ведет соответствующий список задач, находящийся в этом состоянии. Однако для состояния ожидания может быть не один список, а столько, сколько различных видов ресурсов могут вызывать состояние ожидания.
Например, состояний ожидания завершения операции ввода/вывода может быть столько, сколько устройств ввода/вывода содержится в системе.
Процессы и потоки
Чтобы поддерживать мультипрограммирование, ОС должна определить и оформить для себя те внутренне единицы работы, между которыми будет разделяться процессор и другие ресурсы компьютера. В настоящее время в большинстве ОС определены два типа единиц работы:
- Процесс (более крупная единица работы).
- Поток (нить или тред) – более мелкая единица работы, которую требует для своего выполнения процесс.
- Когда говорят о процессах, то тем самым хотят отметить, что ОС поддерживает их обособленность: у каждого процесса имеется свое виртуальное адресное пространство, каждому процессу назначаются свои ресурсы – файлы, окна и др. Такая обособленность нужна для того, чтобы защитить один процесс от другого, поскольку они, совместно используя все ресурсы вычислительной системы, конкурируют друг с другом.
В общем случае процессы просто никак не связаны между собой и могут принадлежать даже различным пользователям, разделяющим одну вычислительную систему. Другими словами, в случае процессов ОС считает их совершенно несвязанными и независимыми. При этом именно ОС отвечает за конкуренцию между процессами по поводу ресурсов.
Для повышения быстродействия процессов есть возможность задействовать внутренний параллелизм в самих процессах.
Например, некоторые операции, выполняемые приложением, могут требовать для своего исполнения достаточно длительного использования ЦП. В этом случае при интерактивной работе с приложением пользователь вынужден долго ожидать завершения заказанной операции и не может управлять приложением до тех пор, пока операция не выполнится до самого конца. Такие ситуации встречаются достаточно часто, например, при обработке больших изображений в графических редакторах. Если же программные модули, исполняющие такие длительные операции, оформлять в виде самостоятельных «подпроцессов» (потоков), которые будут выполняться параллельно с другими «подпроцессами», то у пользователя появляется возможность параллельно выполнять несколько операций в рамках одного приложения (процесса).
Можно выделить следующие отличия потоков от процессов:
- ОС для потоков не должна организовывать полноценную виртуальную машину.
- Потоки не имеют своих собственных ресурсов, они развиваются в том же виртуальном адресном пространстве, могут пользоваться теми же файлами, виртуальными устройствами и иными ресурсами, что и данный процесс.
- Единственное, что потокам необходимо иметь, — это процессорный ресурс. В однопроцессорной системе потоки разделяют между собой процессорное время так же, как это делают обычные процессы, а в многопроцессорной системе могут выполняться одновременно, если не встречают конкуренции из-за обращения к иным ресурсам.
Главное, что обеспечивает многопоточность, — это возможность параллельно выполнять несколько видов операций в одной прикладной программе. За счет чего реализуется эффективное использование ресурсов ЦП, а суммарное время выполнения задач становится меньше.
Например, если табличный процессор или текстовый процессор были разработаны с учетом возможностей многопоточной обработки, то пользователь может запросить пересчет своего рабочего листа или слияние нескольких документов и одновременно продолжать заполнять таблицу или открывать для редактирования следующий документ.
Диспетчер задач WINDOWS
В диспетчере задач отображаются сведения о программах и процессах, выполняемых на компьютере. Кроме того, там можно просмотреть наиболее часто используемые показатели быстродействия процессов.
Диспетчер задач служит для отображения ключевых показателей быстродействия компьютера. Для выполняемых программ можно просмотреть их состояние и завершить программы, переставшие отвечать на запросы. Имеется возможность просмотра активности выполняющихся процессов с использованием до 15 параметров, а также графиков и сведений об использовании ЦП и памяти.
Кроме того, если имеется подключение к сети, можно просматривать состояние сети и параметры ее работы. Если к компьютеру подключились несколько пользователей, можно увидеть их имена, какие задачи они выполняют, а также отправить им сообщение.
На вкладке Процессы отображаются сведения о выполняющихся на компьютере процессах: сведения об использовании ЦП и памяти, счетчике процессов и некоторые другие параметры:
На вкладке Быстродействие, отображаются сведения о счетчике дескрипторов и потоках, параметры памяти:
Потребность в синхронизации потоков возникает только в мультипрограммной ОС и связана с совместным использованием аппаратных и информационных ресурсов компьютера. Синхронизация необходима для исключения гонок (см. далее) и тупиков при обмене данными между потоками, разделении данных, при доступе к процессору и устройствам ввода-вывода.
Синхронизация потоков и процессов заключается в согласовании их скоростей путем приостановки потока до наступления некоторого события и последующей его активизации при наступлении этого события.
Пренебрежение вопросами синхронизации в многопоточной системе может привести к неправильному решению задачи или даже к краху системы.
Пример. Задача ведения базы данных клиентов некоторого предприятия.
Каждому клиенту отводится отдельная запись в базе данных, в которой имеются поля Заказ и Оплата. Программа, ведущая базу данных, оформлена как единый процесс, имеющий несколько потоков, в том числе:
- Поток А, который заносит в базу данных информацию о заказах, поступивших от клиентов.
- Поток В, который фиксирует в базе данных сведения об оплате клиентами выставленных счетов.
Оба эти потока совместно работают над общим файлом базы данных, используя однотипные алгоритмы:
- Считать из файла БД в буфер запись и клиенте с заданным идентификатором.
- Ввести новое значение в поле Заказ (для потока А) или оплата (для потока В).
- Вернуть модифицированную запись в файл БД.
Обозначим шаги 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), тупиком, клинчем или взаимоблокировкой.
Говорят, что в мультизадачной системе процесс находится в состоянии тупика, если он ждет события, которое никогда не произойдет.
Тупиковые ситуации надо отличать от простых очередей, хотя и те и другие возникают при совместном использовании ресурсов и внешне выглядят похоже: процесс приостанавливается и ждет освобождения ресурса. Однако очередь — это нормальное явление, неотъемлемый признак высокого коэффициента использования ресурсов при случайном поступлении запросов. Она возникает тогда, когда ресурс недоступен в данный момент, но через некоторое время он освобождается, и процесс продолжает свое выполнение. Тупик же является в некотором роде неразрешимой ситуацией.
Проблема тупиков включает в себя следующие задачи:
- предотвращение тупиков.
- распознавание тупиков.
- восстановление системы после тупиков.
Тупики могут быть предотвращены на стадии написания программ, то есть программы должны быть написаны таким образом, чтобы тупик не мог возникнуть ни при каком соотношении взаимных скоростей процессов. Так, если бы в предыдущем примере процесс А и процесс В запрашивали ресурсы в одинаковой последовательности, то тупик был бы в принципе невозможен. Второй подход к предотвращению тупиков называется динамическим и заключается в использовании определенных правил при назначении ресурсов процессам, например, ресурсы могут выделяться в определенной последовательности, общей для всех процессов.
В некоторых случаях, когда тупиковая ситуация образована многими процессами, использующими много ресурсов, распознавание тупика является нетривиальной задачей. Существуют формальные, программно-реализованные методы распознавания тупиков, основанные на ведении таблиц распределения ресурсов и таблиц запросов к занятым ресурсам. Анализ этих таблиц позволяет обнаружить взаимные блокировки.
Если же тупиковая ситуация возникла, то не обязательно снимать с выполнения все заблокированные процессы. Можно снять только часть из них, при этом освобождаются ресурсы, ожидаемые остальными процессами, можно вернуть некоторые процессы в область свопинга, можно совершить «откат» некоторых процессов до так называемой контрольной точки, в которой запоминается вся информация, необходимая для восстановления выполнения программы с данного места. Контрольные точки расставляются в программе в местах, после которых возможно возникновение тупика.
Что обозначают в диспетчере задач, счётчик потоков и дескрипторы?
это пищеварительный тракт винды. Потоки-это процедуры программ, дескрипторы-это числа или структуры для взаимодействия процессов.
Супер_ЭнималМастер (2462) 10 лет назад
потоки это файлы открытые для передачи, а дескрипторы это управляющие команды потоками?
GrayМыслитель (5748) 10 лет назад
поток-это исполняемый код в отдельной области памяти, они служат для того, чтобы процесс не ждал выполнения долгоиграющих функций и мог заниматься другими делами. А дескриптор-это грубо говоря случайное число, присвоенное устройствам ввода-вывода.
Остальные ответы
Windows одновременно выполняет много программ, в основном служебных самой Windows. Точнее, квазиодновременно, процессор поочередно, очень быстро для нас, переключается на решение каждой из них. Каждая программа в терминах операционной системы считается отдельным процессом. Отдельные части многих задач могут выполняться какое-то время независимо, поэтому процессы часто делятся на несколько потоков, именно между их выполнением переключается процессор, точнее, каждое процессорное ядро (современные процессоры многоядерные) . Операционная система создает каждому процессу и каждому потоку специальную структуру данных, в которой указывается область памяти, в которой лежат данные потока, его приоритет и так далее. Эта структура данных называется дескриптором потока или процесса, дескрипторы имеют числовые имена — идентификаторы.
Преодолевая границы Windows: дескрипторы
Это уже пятая статья из моей серии публикаций «Преодолевая границы Windows», в которых я рассказываю о максимальном значении и объеме ресурсов, которыми управляет Windows, таких как физическая память, виртуальная память, процессы и потоки:
На этот раз я собираюсь разобраться в реализации дескрипторов, чтобы найти и объяснить существующие для них ограничения. Дескрипторы — это структуры данных, которые представляют собой открытые экземпляры базовых объектов операционной системы, с которыми взаимодействуют приложения; например, файлы, ключи системного реестра, примитивы синхронизации и общая память. Существует два ограничения, связанные с количеством дескрипторов, которое может создать процесс: максимальное число дескрипторов, которое система может установить для процесса, и объем памяти, доступный для хранения дескрипторов и объектов, которые приложение связывает с их дескрипторами.
В большинстве случаев эти ограничения для дескрипторов находятся далеко от тех значений, которые обычно используются приложениями или системой. Однако, приложения, при разработке которых не учитывались эти ограничения, могут достигнуть их неожиданными для разработчиков путями. Чаще всего подобные проблемы возникают из-за того, что срок жизни этого вида ресурсов должен управляться приложениями, и, как в случае с виртуальной памятью, задача управления сроком жизни ресурсов является своего рода вызовом даже для самых лучших разработчиков. Приложение, которое не в состоянии освобождать неиспользуемые ресурсы, вызывает их утечку, что, в конечном счете, может привести к тому, что предел использования ресурса будет достигнут, приводя к странному и трудно диагностируемому поведению как данного, так и других приложений, или же всей системы в целом.
Как обычно, я рекомендую вам прочитать мои предыдущие публикации, поскольку в них объясняются некоторые из понятий, используемых в данной статье (например, выгружаемый пул).
Дескрипторы и объекты
Ядро Windows, работающее в привилегированном режиме, реализованное в образе %SystemRoot%\System32\Ntoskrnl.exe, состоит из различных подсистем, таких как диспетчер памяти, диспетчер процессов, диспетчер ввода/вывода, диспетчер конфигураций (системный реестр), которые является частями исполнительной системы. Каждая из этих подсистем вместе с диспетчером объектов определяет один или более типов для представления ресурсов, которые они выделяют приложениям. Например, диспетчер конфигураций определяет объект «ключ» (Key) для представления открытого ключа системного реестра; диспетчер памяти объект «Секция» (Section) для общей памяти; исполнительная система определяет объекты «семафор» (Semaphore), «мутант» (Mutant, внутреннее название для мьютекса) и «синхронизация событий» (Event synchronization) (эти объекты представляют собой оболочку для структур данных, определенных подсистемой Ядро операционной системы); диспетчер ввода/вывода определяет объект «файл» (File) для представления открытых экземпляров ресурсов драйверов устройств, которые включают в себя файлы файловой системы; и, наконец, диспетчер процессов создает объекты «поток» (Thread) и «процесс» (Process), о которых я рассказывал в своей последней публикации из данной серии. Каждый релиз Windows вводит новые типы объектов, в том числе и Windows 7, которые принес с собой в общей сложности 42 новых типа. Определенный в вашей системы объекты вы можете увидеть при помощи утилиты Winobj от Sysinternals, запущенной с правами администратора, открыв директорию ObjectTypes пространства имен Object Manager:
Когда приложение желает получить управление над одним из этих ресурсов, оно сначала должно вызвать соответствующий API, чтобы создать или открыть ресурс. Например, функция CreateFile открывает или создает файл, функция RegOpenKeyEx открывает ключ реестра, а функция CreateSemaporeEx открывает или создает семафор. Если такая функция успешно выполняется, Windows размещает дескриптор в таблице дескрипторов процесса приложения и возвращает значение этого дескриптора, которое приложение обрабатывает неявно, однако фактически речь идет об индексе возвращенного дескриптора в таблице дескрипторов.
Имея в своем распоряжении дескриптор, приложение делает запросы и управляет объектом, передавая значение дескриптора в такие функции API, как ReadFile , SetEvent , SetThreadPriority и MapViewOfFile . Система может организовать поиск объекта, к которому обращается дескриптор путем индексирования таблицы дескрипторов, чтобы определить местонахождения соответствующей дескриптору записи, которая содержит указатель на объект. Запись дескриптора также хранит информацию об операциях, которые стали доступны процессу, когда он открыл объект, что позволяет системе быть уверенной в том, что процесс не сможет выполнять над объектом операции, на которые у этого процесса нет разрешения. Например, если процесс успешно открыл файл для чтения, то запись дескриптора выглядела примерно так:
Если бы этот процесс попытался бы что-то записать в файл, то функция завершила выполнение с ошибкой, поскольку подобный вид доступа к файлу не был предоставлен, а факт кэширования доступа на чтение означает, что система не должна снова повторять более затратную в плане ресурсов проверку прав доступа.
Максимальное число дескрипторов
Чтобы исследовать первое ограничение вы можете воспользоваться инструментальным средством Testlimit, которое я уже использовал в рамках данной серии статей для того, чтобы опытным путем изучить ограничения на ресурсы системы. Его можно скачать на странице Windows Internals здесь . Для определения количества дескрипторов, которое может создать процесс, Testlimit используется с параметром -h, который указывает ему создать столько дескрипторов, сколько возможно. Это достигается путем создания объекта event с помощью функции CreateEvent и последующего неоднократного дублирования возвращаемого системой дескриптора с помощью функции DuplicateHandle . Используя дублирование, Testlimit избегает необходимости создания новых объектов и все ресурсы, потребляемые этим инструментов, расходуются для записей таблицы дескрипторов. Вот результат работы Testlimit с ключом -h в 64-битной системе:
Этот результат, однако, не отображает общее количество дескрипторов, которые может создать процесс, поскольку системные библиотеки DLL открывают различные объекты во время инициализации процесса. Общее число дескрипторов процесса вы можете увидеть, добавив соответствующую колонку в диспетчере задач или Process Explorer. Общее цифра для Testlimit в данном случае равна 16’771’680:
Когда вы запускаете Testlimit на 32-битной системе, число дескрипторов будет немного отличаться:
Общее число дескрипторов также другое, 16’744’448:
Чем обуславливаются эти различия? Ответ состоит в том, что исполнительная система, ответственная за управление таблицей дескрипторов, устанавливает ограничение на количество дескрипторов для каждого процесса, а также на размер записи в таблице дескрипторов. Здесь мы имеем дело с одним из тех редких случаев, когда Windows устанавливает жесткое ограничение на использование ресурса, так что в данном случае исполнительная система определяет число 16’777’216 (16*1024*1024) как максимальное количество дескрипторов, которое может быть выделено процессу. Любой процесс, которые имеет более десяти тысяч дескрипторов одновременно в какой-либо момент времени, весьма вероятно имеет либо серьезные недочеты, допущенные при его проектировании, или утечку дескрипторов. Так что предел в 16 миллионов дескрипторов практически недостижим и призван помочь предотвратить утечку памяти, вызванную вмешательством в работу процесса со стороны остальной системы. Чтобы понять причину того, почему число, отображаемое в диспетчере задач, отличается от жестко установленного максимума, требуется рассмотреть то, каким образом исполнительная система организовывает таблицу дескрипторов.
Запись таблицы дескрипторов должна иметь достаточный размер для того, чтобы хранить маску прав доступа и указатель на объект. Маска доступа является 32-битной, но размер указателя, очевидно, зависит от того, является система 32-битной или 64-битной. Следовательно, запись дескриптора занимает 8 байт на 32-битной Windows и 12-байт на 64-битной Windows. 64-битная Windows дополняет структуры данных записи дескриптора до 64-битных границ, так что 64-битная запись дескриптора фактически занимает 16 байт. Вот определение записи дескрипторов на 64-битной Windows, отображенное в отладчике ядра с помощью команды dt (dump type):
Здесь мы видим, что данная структура содержит в себе и другую информацию, помимо указателя на объект и маски доступа, выделенных на скриншоте.
Исполнительная система размещает таблицы дескрипторов в блоки, имеющие размер страницы, которые она делит на записи таблицы дескрипторов. Это означает, что страница, которая занимает 4096 байт и на системах x86, и на системах x64, может сохранить 512 записей в 32-битной Windows и 256 записей в 64-битной Windows. Исполнительная система определяет максимальное число страниц, которые она может выделить под записи дескрипторов, путем деления жестко установленного максимума (16’777’216) на число записей дескрипторов на странице; для 32-битной Windows это число равно 32’768, а для 64-битной Windows — 65’536. Поскольку исполнительная система использует первую запись на каждой странице для своей собственной идентификационной информации, действительное количество дескрипторов, доступных для процесса, следует получать, вычитая из 16,777,216 полученные выше числа, что объясняет результаты, полученные при запуске Testlimit: 16’777’216 — 65’536 = 16’711’680 и 16’777’216 — 32’768 = 16’744’488.
Дескрипторы и выгружаемый пул
Вторым ограничением, касающимся дескрипторов, является объем памяти, требуемой для хранения таблицы дескрипторов, который исполнительная система выделяет из выгружаемого пула. Исполнительная система для отслеживания выделяемых ею под таблицы дескрипторов страниц использует трехуровневую схему, подобную той, которую используют модули управления памятью (MMU) процессора для руководства трансляциями виртуальных адресов в физические. Мы уже рассматривали с вами организацию нижнего и среднего уровней, которые фактически хранят в себе записи таблицы дескрипторов. Верхний уровень служит в качестве указателей на таблицы среднего уровня и включает в себя 1024 записи на страницу в 32-битной Windows. Отсюда следует, что общее количество страниц, требуемых для хранения максимального числа дескрипторов для 32-битной Windows можно вычислить как 16’777’216/512*4096, что равно 128 Мб. Это совпадает с показателями использования Testlimit выгружаемого пула, которые показывает диспетчер задач:
В 64-битной версии Windows на верхнем уровне содержится 256 указателей на страницу. Это означает в общем для размещения полной таблицы дескрипторов используется 256 Мб выгружаемого пула (16’777’216/256*4096). Правильность данных вычислений подтверждается показателями использования Testlimit выгружаемого пула на 64-битной Windows:
Объема выгружаемого пула более чем достаточно, чтобы сохранить эти структуры данных, однако, как я уже говорил ранее, процесс, который создает слишком много дескрипторов, почти наверняка исчерпает какой-то другой ресурс, и, если он достигнет ограничения на количество дескрипторов для одного процесса, то ему не удастся открыть никакие другие объекты.
Утечки дескрипторов
Для процесса, допускающего утечку дескрипторов характерно то, что число потерянных дескрипторов постоянно возрастает. Причина этого кроется в том, что утечка дескрипторов очень коварна — в отличие от случая с Testlimit, который создавал дескрипторы для одного и того же объекта, процесс, имеющий утечку дескрипторов, вероятнее всего теряет вместе с ними и объекты. Например, если процесс создает события, но не может закрыть их, он создает утечку как записей дескрипторов, так и объектов событий. Объекты «event» располагаются в невыгружаемом пуле, так что данная утечка затронет в дополнение к выгружаемому пулу и невыгружаемый пул.
Вы можете визуально определить объекты, доступ к которым потерял процесс, используя представление дескрипторов в Process Explorer, поскольку там новые дескрипторы выделены зеленым, а закрытые — красным; если вы увидите много зеленых записей при малом количестве красных, значит вы, скорее всего, столкнулись с утечкой. Чтобы увидеть подобное выделение дескрипторов Process Explorer в действии, вы можете открыть процесс командной строки и, выбрав этот процесс в Process Explorer, перейти к просмотру дескрипторов, после чего следует сменить текущую директорию в командной строке. Дескриптор старой рабочей директории подсветится красным, а новой — зеленым:
По умолчанию Process Explorer показывает только дескрипторы, которые указывают на объекты, имеющие имена, что означает, что вы не увидите всех дескрипторов процесса, если не включите опцию «Show Unnamed Handles and Mappings» в меню View. Вот некоторые безымянные дескрипторы из таблицы дескрипторов командной строки:
Как и в случае с большинством других ошибок, только разработчик кода, из-за которого происходит утечка, может исправить это. Если вы обнаружили утечку у процесса, который состоит из нескольких компонентов или расширений, например, Explorer, Service Host или Internet Explorer, то главный вопрос состоит в том, какая из этих частей ответственна за утечку. Определение такого компонента позволило бы вам избежать появления проблемы, отключив или удалив проблемное расширение, проверить его на наличие обновлений, исправляющих эту ошибку или сообщить о ней разработчику.
К счастью, Windows включает в себя средство отслеживания дескрипторов, которое вы можете использовать для установления факта утечки и определения ответственного за эту утечку программного обеспечения. Оно работает с каждым процессом в отдельности и активируется исполнительной системой для записи активности стека каждый раз, когда какой-либо дескриптор создается или закрывается. Вы можете воспользоваться этим инструментом или при помощи утилиты Application Verifier , которую можно бесплатно скачать с сайта Microsoft, или воспользовавшись отладчиком Windows (Windbg) . Если вы хотите, чтобы система проследила за активностью дескрипторов процесса, начиная с его запуска, то вам нужно использовать Application Verifier. В остальных случаях вам нужно использовать отладчик и команду !htrace , чтобы увидеть информацию об активности процесса.
Чтобы продемонстрировать отслеживание активности в действии, я запустил Windbg и подключился к командной строке, которую я запустил ранее. Чтобы включить отслеживание дескрипторов, я ввел команду !htrace с ключом -enable:
Я позволил процессу продолжать работу и снова сменил директорию. После этого я переключился обратно на Windbg, остановил выполнение процесса и запустил команду htrace без параметров, которая выдает список всех открытых и закрытых операций, которые выполнил процесс, начиная с предыдущего запуска команды !htrace с параметром snapshot или с того момента, когда была включена запись активности дескрипторов. Вот результаты работы этой команды для той же сессии отладчика:
Здесь перечислены события, начиная с самой последней операции, так что, если читать снизу, мы увидим, что командная строка открыла дескриптор 0xb8, затем закрыла его, потом открыла дескриптор 0x22c и в конце закрыла дескриптор 0xec. Process Explorer отметил бы дескриптор 0x22c зеленым и 0xec красным, если бы он был обновлен после смены директории, но, по всей вероятности, не увидел бы 0xb8, если бы обновление не произошло между открытием и закрытием этого дескриптора. Стек для открытия 0x22c показывает, что данная операция стала результатом выполнения командной строкой (cmd.exe) своей функции ChangeDirectory. Если добавить в Process Explorer колонку Handle, она подтвердит, что новый дескриптор — 0x22c:
Если вы ищите только утечки, то вам нужно использовать !htrace с параметром -diff, которая показывает только новые дескрипторы, начиная с последней засечки или с начала запуска отслеживания активности. Как и ожидалось, в результате выполнения этой команды мы видим только дескриптор 0x22c:
Прекрасным источником советов о том, как можно устранить утечки дескрипторов является интервью инженера по технической поддержке Microsoft Джеффа Дэйли (Jeff Dailey) для Channel 9.
В следующий раз я рассмотрю ограничения, установленные для таких основанных на дескрипторах ресурсов, как объекты GDI и USER. Дескрипторы этих ресурсов управляются подсистемой Windows, отличной от исполнительной системы, а потому используют другие ресурсы и имеют другие ограничения.
Sysadminium
Работа операционной системы 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«. Затем нажмите на нём правой копкой мыши и выберите «Подробно»:
Вы переключитесь на вкладку «Подробно» с выделенным процессом «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:
Далее нужно настроить сервер символических имен. Если это не сделать, при двойном щелчке на процессе, на вкладке Threads (потоки) вы получите сообщение о том, что символические имена не настроены:
Для начала скачиваем установщик «Пакет SDK для Windows 10».
Устанавливать все не нужно, достаточно при установки выбрать «Debugging Tools for Windows«:
Для настройки символических имен перейдите в меню 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:
- Смена цветового выделения — 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»:
В колонках видна информация по каждому потоку:
- TID — идентификатор потока.
- CPU — загрузка процессора.
- Cycles Delta — общее количество циклов процессора, которое этот процесс использовал с момента последнего обновления работы Process Explorer. Скорость обновления программы можно настроить, указав например 5 минут.
- Suspend Count — количество приостановок потока.
- Service — название службы.
- Start Address — начальный адрес процедуры, который начинает выполнение нового потока. Выводится в формате:«модуль!функция».
При выделении потока, снизу показана следующую информация:
- Идентификатор потока.
- Время начала работы потока.
- Состояние потока.
- Время выполнения в режиме ядра и в пользовательском режиме.
- Счетчик переключения контекста для центрального процессора.
- Количество циклов процессора.
- Базовый приоритет.
- Динамический приоритет (текущий).
- Приоритет ввода / вывода.
- Приоритет памяти.
- Идеальный процессор (предпочтительный процессор).
Есть также кнопки:
- Stack — посмотреть стек процесса;
- Module — посмотреть свойства запущенного исполняемого файла;
- Permission — посмотреть права на поток;
- Kill — завершить поток;
- Suspend — приостановить поток.
Задания в Process Explorer
Process Explorer может выделить процессы, управляемые заданиями. Чтобы включить такое выделение откройте меню «Options» и выберите команду «Configure Colors», далее поставьте галочку «Jobs»:
Более того, страницы свойств таких процессов содержат дополнительную вкладку Job с информацией о самом объекте задания. Например приложение Skype работает со своими процессами как за заданием:
Запустите командную строку и введите команду:
>runas /user:\ cmd
Таким образом вы запустите еще одну командную строку от имени этого пользователя. Служба Windows, которая выполняет команды runas, создает безымянное задание, чтобы во время выхода из системы завершить процессы из задания.
В новой командной строке запустите блокнот:
>notepad.exe
Далее запускаем Process Explorer и находим такое дерево процессов:
Как видим, процесс cmd и notepad это процессы связанные с каким-то заданием. Если дважды кликнуть по любому из этих процессов и перейти на вкладку Job, то мы увидим следующее:
Тут видно что эти два процесса работают в рамках одного задания.
Имя статьи
Процессы WindowsРабота операционной системы Windows основана на работе процессов. В этой статье разберём что такое Windows процессы, их свойства, состояния и другое