如何将句柄传递给子进程

时间:2011-09-14 17:34:05

标签: c winapi

我正在尝试将互斥锁句柄传递给子进程槽命令行或其他任何方式。

我该怎么做? 我如何从孩子那里获得互斥锁?

这就是我创建子进程的方式:

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 trough命令行,然后在子进程中将其转换回来:

mutexValue=atoi(argv[2]);

Mutex=(HANDLE)mutexValue;

我的问题,是否可以进行(HANDLE)投射?

2 个答案:

答案 0 :(得分:5)

两个选项:

  1. 您可以使用命名对象。进程A使用名称创建Mutex,然后生成进程B.进程B然后调用具有相同名称的OpenMutex或CreateMutex,它将获得相同互斥锁的句柄。

    缺点是名称选择。如果您发生名称冲突,则可能会产生不可预测的结果。攻击者可以创建具有相同名称的互斥锁并创建拒绝服务情况。解决此问题的一种方法是随机生成名称。例如,进程A可以为名称生成GUID,然后将命令行上的GUID(作为字符串)传递给进程B.

  2. 您可以使用inheritance。子进程可以从父进程继承许多类型的句柄,包括互斥句柄。在CreateProcess命令(您的示例已在进行)中设置bInheritHandles参数,并将命令行上的句柄值(作为字符串)传递给子进程。然后,子进程可以将命令行字符串转换回值,然后开始使用它。两个过程中的值相同。

  3. 此技术与命名对象技术没有相同的缺点。

    继承的工作示例(错误检查已省略):

    #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 :(得分:1)

在创建子进程之前创建互斥锁并使其可继承(在CreateMutex的lpMutexAttributes参数中将bInheritHandle设置为TRUE)。这样您就可以在命令行中传递句柄。

或者使用DuplicateHandle并通过其他机制传递句柄(例如,使用管道作为子进程的STDIN)。