Зачем нужны дочерние процессы



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

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

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

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

 

Один из самых удобных способов, обеспечивающих совместный доступ

к данным, - использование файлов, проецируемых в память.

 

Если Вы хотите создать новый процесс, заставить его выполнить какие-либо операции и дождаться их результатов, напишите примерно такой код:

 

PROCESS_INFORMATION pinfo;
DWORD dwExitCode;

          // порождаем дочерний процесс
BOOL success = CreateProcess(..., &pinfo};

if (success)

{

      // закрывайте описатель потока, как только

      // необходимость в нем отпадает!
  CloseHandle(pinfo.hThread);


      // приостанавливаем выполнение родительского процесса,
      // пока не завершится дочерний процесс
  WaitForSingleObject(pinfo.hProcess, INFINITE);

      // дочерний процесс завершился; получаем код его завершения
  GetExitCodeProcess(pinfo.hProcess, &dwExitCode);

     // закрывайте описатель процесса, как только

     // необходимость в нем отпадает!
  CloseHandle(pinfo.hProcess);

}

 

В этом фрагменте кода создается новый процесс и, если это прошло успешно, вызывается функция WaitForSingleQbject :

 

DWORD WaitForSingleObject(HANDLE hObject, DWORD dwTimeOut);

 

Функция задерживает выполнение кода до тех пор, пока объект, определяемый параметром bObject , не перейдет в свободное (незанятое) состояние. Объект "процесс" переходит в такое состояние при его завершении. Поэтому вызов WaitForSingleObject приостанавливает выполнение потока родительского процесса до завершения порожденного им процесса.

 Когда WaitForSingleObject вернет управление, можно узнать код завершения дочернего процесса через функцию GetExitCodeProcess .

Обращение к CloseHandle в приведенном выше фрагменте кода заставляет систему уменьшить значения счетчиков объектов "поток" и "процесс" до нуля и тем самым освободить память, занимаемую этими объектами.

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

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

 

PROCESS_INFORMATION pinfo;

BOOLsuccess = CreateProcess( , &pinfo);
if (success)

{

      // разрешаем системе уничтожить обьекты ядра "процесс" и "поток"
      // сразу после создания дочернего процесса
   CloseHandle(pinfo.hThread);
    CloseHandle(pinfo.hProcess);

}


Дата добавления: 2019-07-15; просмотров: 447; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!