Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 112 стр.

UptoLike

но превратить псевдоописатель процесса в настоящий описатель, действу-
ющий только в текущем процессе:
HANDLE hrealThread;
DuplicateHandle(
GetCurrentProcess(), GetCurrentProcess(),
GetCurrentProcess(), &hrealThread,
DUPLICATE_SAME_ACCESS, FALSE, 0
);
У процессов и потоков есть интересная особенность – объекты ядра,
представляющие процесс и поток, сразу после создания имеют счетчик
использования не менее двух: во-первых, это описатель, возвращенный
функцией, и, во-вторых, объект используется работающим потоком.
В итоге завершение потока и завершение последнего потока в процессе
не приводят к удалению соответствующих объектов – они будут сохра-
няться все время, пока существуют их описатели. Это сделано для того,
чтобы уже после завершения работы потока или процесса можно было по-
лучить от него какую-либо информацию, чаще всего – код завершения
(функции GetExitCodeThread и GetExitCodeProcess);
Объекты ядра «процесс» и «поток» поддерживают также интерфейс
синхронизируемых объектов, так что их можно использовать для синхро-
низации работы: поток считается занятым до завершения, а процесс занят
до тех пор, пока в нем есть хоть один работающий поток.
Если ни синхронизация с этими объектами, ни получение кодов за-
вершения не требуются разработчику, надо сразу после создания соответ-
ствующего объекта закрывать его описатель.
В Windows для задания приоритета работающего потока используют
понятия классов приоритетов и относительных приоритетов в классе. При
этом класс приоритета связывается с процессом, а относительный при-
оритет – с потоком, исполняющимся в данном процессе.
Соответственно Win32 API предоставляет функции для изменения
класса приоритета для процесса (GetPriorityClass, SetPriorityClass) и
для изменения относительного приоритета потока (GetThreadPriority и
SetThreadPriority).
Планировщик операционной системы может динамически коррек-
тировать приоритет потока, кратковременно повышая уровень. Разработ-
чикам предоставлена возможность отказаться от этой возможности или,
наоборот, задействовать ее (функции GetProcessPriorityBoost,
SetProcessPriorityBoost, GetThreadPriorityBoost и
SetThreadPriorityBoost).
Основы многозадачности
211
BOOL DuplicateHandle(
HANDLE hFromProcess, HANDLE hSourceHandle,
HANDLE hToProcess, LPHANDLE lpResultHandle,
DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions
);
Существенно проследить, чтобы все создаваемые описатели закрыва-
лись вызовом функции CloseHandle, включая описатели, созданные функ-
цией DuplicateHandle. Хорошая практика при разработке приложений –
проводить мониторинг выделяемых описателей и количества объектов в
процессе (например, с помощью таких стандартных средств как менеджер
задач или оснастка «производительность» панели управления).
6.2.3.2. Описатели процесса и потока
Для взаимодействия потоков и процессов между собой необходимы
средства, обеспечивающие идентификацию соответствующих объектов.
В Windows для идентификации процессов и потоков используют их описа-
тели (HANDLE) и идентификаторы (DWORD). Описатели идентифицируют в
данном случае объект ядра, представляющий процесс или поток, при дос-
тупе к которому, как ко всякому объекту ядра, учитывается контекст защи-
ты, проверяются права доступа и т.д. Идентификаторы процесса и потока,
назначаемые при их создании, исполняют роль уникальных имен.
Описатели и идентификаторы процессов и потоков можно получить
при создании соответствующих объектов. Кроме того, можно узнать иден-
тификаторы текущего процесса и потока (GetCurrentThreadId,
GetCurrentProcessId), или по описателю узнать соответствующий иденти-
фикатор (GetProcessId и GetThreadId). Функции OpenProcess и OpenThread
позволяют получить описатели этих объектов по их идентификатору.
Функции GetCurrentProcess и GetCurrentThread возвращают описате-
ли текущего процесса и потока, однако возвращаемое ими значение не яв-
ляется настоящим описателем, а представлено некоторой константой, по-
лучившей название «псевдоописатель». Эта константа, использованная
вместо описателя потока или процесса, рассматривается как описатель
процесса/потока, сделавшего вызов системной функции. Псевдоописате-
лями можно свободно пользоваться в рамках процесса (потока), в котором
они получены, а при попытке передать их другому процессу или потоку
они будут рассматриваться как описатели того процесса (потока), в кон-
тексте которого используются.
В тех случаях, когда необходимо дать другому процессу или потоку
доступ к данным описателям, нужно с помощью DuplicateHandle сделать с
них «копии», которые будут являться настоящими описателями в контек-
сте процесса-получателя. Так, например, с помощью этой функции мож-
210
CIL и системное программирование в Microsoft .NET
210                         CIL и системное программирование в Microsoft .NET   Основы многозадачности                                             211


     BOOL DuplicateHandle(                                                      но превратить псевдоописатель процесса в настоящий описатель, действу-
        HANDLE hFromProcess, HANDLE hSourceHandle,                              ющий только в текущем процессе:
        HANDLE hToProcess, LPHANDLE lpResultHandle,
        DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions                  HANDLE hrealThread;
     );                                                                              DuplicateHandle(
     Существенно проследить, чтобы все создаваемые описатели закрыва-                   GetCurrentProcess(), GetCurrentProcess(),
лись вызовом функции CloseHandle, включая описатели, созданные функ-                    GetCurrentProcess(), &hrealThread,
цией DuplicateHandle. Хорошая практика при разработке приложений –                      DUPLICATE_SAME_ACCESS, FALSE, 0
проводить мониторинг выделяемых описателей и количества объектов в                   );
процессе (например, с помощью таких стандартных средств как менеджер
задач или оснастка «производительность» панели управления).                          У процессов и потоков есть интересная особенность – объекты ядра,
                                                                                представляющие процесс и поток, сразу после создания имеют счетчик
6.2.3.2. Описатели процесса и потока                                            использования не менее двух: во-первых, это описатель, возвращенный
     Для взаимодействия потоков и процессов между собой необходимы              функцией, и, во-вторых, объект используется работающим потоком.
средства, обеспечивающие идентификацию соответствующих объектов.                В итоге завершение потока и завершение последнего потока в процессе
В Windows для идентификации процессов и потоков используют их описа-            не приводят к удалению соответствующих объектов – они будут сохра-
тели (HANDLE) и идентификаторы (DWORD). Описатели идентифицируют в              няться все время, пока существуют их описатели. Это сделано для того,
данном случае объект ядра, представляющий процесс или поток, при дос-           чтобы уже после завершения работы потока или процесса можно было по-
тупе к которому, как ко всякому объекту ядра, учитывается контекст защи-        лучить от него какую-либо информацию, чаще всего – код завершения
ты, проверяются права доступа и т.д. Идентификаторы процесса и потока,          (функции GetExitCodeThread и GetExitCodeProcess);
назначаемые при их создании, исполняют роль уникальных имен.                         Объекты ядра «процесс» и «поток» поддерживают также интерфейс
     Описатели и идентификаторы процессов и потоков можно получить              синхронизируемых объектов, так что их можно использовать для синхро-
при создании соответствующих объектов. Кроме того, можно узнать иден-           низации работы: поток считается занятым до завершения, а процесс занят
тификаторы текущего процесса и потока (GetCurrentThreadId,                      до тех пор, пока в нем есть хоть один работающий поток.
GetCurrentProcessId), или по описателю узнать соответствующий иденти-                Если ни синхронизация с этими объектами, ни получение кодов за-
фикатор (GetProcessId и GetThreadId). Функции OpenProcess и OpenThread          вершения не требуются разработчику, надо сразу после создания соответ-
позволяют получить описатели этих объектов по их идентификатору.                ствующего объекта закрывать его описатель.
     Функции GetCurrentProcess и GetCurrentThread возвращают описате-                В Windows для задания приоритета работающего потока используют
ли текущего процесса и потока, однако возвращаемое ими значение не яв-          понятия классов приоритетов и относительных приоритетов в классе. При
ляется настоящим описателем, а представлено некоторой константой, по-           этом класс приоритета связывается с процессом, а относительный при-
лучившей название «псевдоописатель». Эта константа, использованная              оритет – с потоком, исполняющимся в данном процессе.
вместо описателя потока или процесса, рассматривается как описатель                  Соответственно Win32 API предоставляет функции для изменения
процесса/потока, сделавшего вызов системной функции. Псевдоописате-             класса приоритета для процесса (GetPriorityClass, SetPriorityClass) и
лями можно свободно пользоваться в рамках процесса (потока), в котором          для изменения относительного приоритета потока (GetThreadPriority и
они получены, а при попытке передать их другому процессу или потоку             SetThreadPriority).
они будут рассматриваться как описатели того процесса (потока), в кон-               Планировщик операционной системы может динамически коррек-
тексте которого используются.                                                   тировать приоритет потока, кратковременно повышая уровень. Разработ-
     В тех случаях, когда необходимо дать другому процессу или потоку           чикам предоставлена возможность отказаться от этой возможности или,
доступ к данным описателям, нужно с помощью DuplicateHandle сделать с           наоборот, задействовать ее (функции GetProcessPriorityBoost,
них «копии», которые будут являться настоящими описателями в контек-            SetProcessPriorityBoost, GetThreadPriorityBoost и
сте процесса-получателя. Так, например, с помощью этой функции мож-             SetThreadPriorityBoost).