Московский государственный технический университет им. Н.Э. Баумана
Опубликован: 28.06.2006 | Доступ: свободный | Студентов: 12459 / 340 | Оценка: 4.54 / 3.83 | Длительность: 22:03:00
ISBN: 978-5-9556-0055-0
Лекция 14:

Взаимодействие процессов и потоков

Создание процессов

Для создания процессов используются функции CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW и CreateProcessWithTokenW. Функция CreateProcess создает новый процесс, который будет исполняться от имени текущего пользователя потока, вызвавшего эту функцию. Функция CreateProcessAsUser позволяет запустить процесс от имени другого пользователя, который идентифицируется его маркером безопасности (security token); однако вызвавший эту функцию поток должен принять меры к правильному использованию реестра, так как профиль нового пользователя не будет загружен. Функции CreateProcessWithTokenW и CreateProcessWithLogonW позволяют при необходимости загрузить профиль пользователя и, кроме того, функция CreateProcessWithLogonW сама получает маркер пользователя по известному учетному имени, домену и паролю.

#include <windows.h>
#define DEFAULT_SECURITY  (LPSECURITY_ATTRIBUTES)NULL

int main( void )
{
  STARTUPINFO         si;
  PROCESS_INFORMATION  pi;
  memset( &si, 0, sizeof(si) );
  memset( &pi, 0, sizeof(pi) );
  si.cb = sizeof(si);
  CreateProcess(
    NULL, "cmd.exe", DEFAULT_SECURITY, DEFAULT_SECURITY,
    FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi
  );
  CloseHandle( pi.hThread );
  WaitForSingleObject( pi.hProcess, INFINITE );
  CloseHandle( pi.hProcess );
  return 0;
}

При создании процесса ему можно передать описатели каналов ( CreatePipe ), предназначенные для перенаправления stdin, stdout и stderr. Описатели каналов должны быть наследуемыми.

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

Адресное пространство процесса и проецирование файлов

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

Доступная пользователю часть адресного пространства процесса выделяется реально не в физической оперативной памяти, а в файлах, данные которых проецируются на соответствующие фрагменты адресного пространства. Выделение памяти без явного указания проецируемого файла приведет к тому, что область для проецирования будет автоматически выделяться в файле подкачки страниц. Физическая оперативная память в значительной степени является кэшем для данных файлов. Выделение физической оперативной памяти применяется очень редко, например, средствами расширения адресного пространства (Address Windowing Extension, AWE), позволяющими использовать более чем 4Г адресного пространства в 32-х разрядном приложении Win32.

Важная особенность средств управления адресным пространством и проецированием файлов - они используют так называемую гранулярность выделения ресурсов (ее можно узнать с помощью функции GetSystemInfo ); в современных версиях Win32 гранулярность составляет 64К. Это означает, что если вы попробуете спроецировать в память файл размером 100 байт, то в адресном пространстве будет занят фрагмент в 65536 байт длиной, из которого реально будут заняты только первые 100 байт.

Для управления адресным пространством предназначены функции VirtualAlloc, VirtualFree, VirtualAllocEx, VirtualFreeEx, VirtualLock и VirtualUnlock. С их помощью можно резервировать пространство в адресном пространстве процесса (без передачи физической памяти из файла) и управлять передачей памяти из файла подкачки страниц указанному диапазону адресов.

Механизмы проецирования файлов в память различаются для обычных и для исполняемых файлов. Функции создания процессов ( CreateProcess...) и загрузки библиотек ( LoadLibrary, LoadLibraryEx ), помимо специфичных действий, выполняют проецирование исполняемых файлов в адресное пространство процесса; при этом учитывается их деление на сегменты, наличие секций импорта, экспорта и релокаций и др. Обычные файлы проецируются как непрерывный блок данных на непрерывный диапазон адресов.

Для явного проецирования файлов используется специальный объект ядра проекция файла (file mapping object). Этот объект предназначен для описания файла, который может быть спроецирован в память, но реального отображения файла или его части в память при создании проекции не происходит. Описатель объекта "проекция файла" можно получить с помощью функций CreateFileMapping и OpenFileMapping. Для проецирования файла или его части в память предназначены функции MapViewOfFile, MapViewOfFileEx и UnmapViewOfFile:

#include <windows.h>
#define DEFAULT_SECURITY  (LPSECURITY_ATTRIBUTES)NULL
int main( void )
{
  HANDLE  hFile, hMapping;
  LPVOID  pMapping;
  LPSTR   p;
  int     i;
  hFile = CreateFile(
    "abc.dat", GENERIC_WRITE|GENERIC_READ,
    FILE_SHARE_WRITE, DEFAULT_SECURITY,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
  );
  hMapping = CreateFileMapping(
    hFile, DEFAULT_SECURITY, PAGE_READWRITE, 0, 256, NULL
  );
  pMapping = MapViewOfFile( hMapping, FILE_MAP_WRITE, 0,0, 0 );
  for ( p = (LPSTR)pMapping, i=0; i<256; i++ ) *p++ = (char)i;
  UnmapViewOfFile( hMapping );
  CloseHandle( hMapping );
  CloseHandle( hFile );
  return 0;
}
Анастасия Булинкова
Анастасия Булинкова
Рабочим названием платформы .NET было