Как передать дескриптор дочернему процессу - PullRequest
4 голосов
/ 14 сентября 2011

Я пытаюсь передать дескриптор мьютекса в командную строку дочернего процесса или любым другим способом.

Как я могу это сделать?Как мне получить доступ к мьютексу от ребенка?

Вот как я создаю дочерний процесс:

HANDLE ghMutex;

     if( !CreateProcess( _T("C:\\Users\\Kumppler\\Documents\\Visual Studio 2010\\Projects\\teste3\\Debug\\teste3.exe"),   // No module name (use command line)
                aux2,                              // Command line
                NULL,                              // Process handle not inheritable
                NULL,                              // Thread handle not inheritable
                TRUE,                              // Set handle inheritance to TRUE
                STARTF_USESTDHANDLES,              // inherit the standard input, standard output, and standard error handles
                NULL,                              // Use parent's environment block
                NULL,                              // Use parent's starting directory 
                &si[j],                            // Pointer to STARTUPINFO structure
                &pi[j] )                           // Pointer to PROCESS_INFORMATION structure
            )                     

РЕДАКТИРОВАТЬ:

Мне нужно использовать мьютексдля более чем одного дочернего процесса, это нормально?

Итак, вот что я делаю прямо сейчас:

HANDLE ghMutex;
int mutex;
char mutexstring[7];

mutex=(int)ghMutex;
itoa(mutexValue,mutexString,10);

Я передам командную строку через mutexString, а затем преобразуювернемся к дочернему процессу:

mutexValue=atoi(argv[2]);

Mutex=(HANDLE)mutexValue;

Мой вопрос, можно ли выполнять кастинг (HANDLE) ??

Ответы [ 3 ]

5 голосов
/ 14 сентября 2011

Два варианта:

  1. Вы можете использовать именованные объекты.Процесс A создает Mutex с именем, а затем порождает процесс B. Затем процесс B вызывает OpenMutex или CreateMutex с тем же именем, и он получает дескриптор для того же мьютекса.

    Недостатки в выборе имени.Если у вас есть столкновение имен, вы можете получить непредсказуемые результаты.Злоумышленник может создать мьютекс с тем же именем и создать ситуацию отказа в обслуживании.Один из способов справиться с этим - генерировать имя случайным образом.Например, процесс A может сгенерировать GUID для имени, а затем передать этот GUID (в виде строки) в командной строке процессу B.

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

Этот метод не имеет тех же недостатков, что и метод именованного объекта.

Рабочий пример наследования (проверка ошибокelided):

#include <cstddef>
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>

void DoParentWork() {
  std::wcout << L"Parent:  Creating an inheritable event..." << std::endl;
  SECURITY_ATTRIBUTES security = {
    sizeof(security), nullptr, /* bInheritHandle = */ TRUE
  };
  HANDLE hEvent = ::CreateEventW(&security, /* bManualReset = */ TRUE,
                                 /* bInitialState = */ FALSE, nullptr);

  std::wstringstream ssCommand;
  ssCommand << L"foo.exe " << reinterpret_cast<std::size_t>(hEvent);
  std::wstring strCmd = ssCommand.str();;

  std::wcout << L"Parent:  Starting child process..." << std::endl;
  STARTUPINFO start_info = {sizeof(start_info)};
  PROCESS_INFORMATION proc_info = {0};
  ::CreateProcessW(L"foo.exe", &strCmd[0], nullptr, nullptr,
                   /* bInheritHandles = */ TRUE, 0, nullptr, nullptr,
                   &start_info, &proc_info);
  ::CloseHandle(proc_info.hThread);
  ::CloseHandle(proc_info.hProcess);

  std::wcout << L"Parent:  Waiting for the child to signal the event."
             << std::endl;
  if (::WaitForSingleObject(hEvent, 10*1000) == WAIT_OBJECT_0) {
    std::wcout << L"Parent:  The event was signaled." << std::endl;
  } else {
    std::wcout << L"Parent:  Timed out waiting for the event."
               << std::endl;
  }
  ::CloseHandle(hEvent);
}

void DoChildWork(const char *pszEvent) {
  std::stringstream ss(pszEvent);
  UINT_PTR iEvent;
  ss >> iEvent;
  HANDLE hEvent = reinterpret_cast<HANDLE>(iEvent);
  std::cout << "Child:  Event handle "
            << reinterpret_cast<std::size_t>(hEvent) << std::endl;
  ::Sleep(2000);
  std::cout << "Child:  Signalling the event." << std::endl;
  ::SetEvent(hEvent);
}

int main(int cArgs, char *ppszArgs[]) {
  if (cArgs > 1) DoChildWork(ppszArgs[1]);
  else DoParentWork();
  return 0;
}
1 голос
/ 15 сентября 2011

Либо создайте мьютекс перед созданием дочернего процесса и сделайте его наследуемым (установите для bInheritHandle значение TRUE в параметре lpMutexAttributes для CreateMutex).Таким образом, вы можете передать дескриптор в командной строке.

Или использовать DuplicateHandle и передать дескриптор через какой-то другой механизм (например, использовать канал в качестве STDIN для дочернего процесса).

0 голосов
/ 14 сентября 2011

Мьютекс и дескрипторы лежат в адресном пространстве процесса, который изначально его создал. Так что вы не можете просто «передать» его в другой процесс.

На этой странице объясняется, как выполнять межпроцессную синхронизацию:

http://msdn.microsoft.com/en-us/library/ms684123%28v=vs.85%29.aspx

Идея заключается в создании мьютекса с использованием имен объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...