2011-09-14 33 views
4

我正在尝试将一个互斥句柄传递给子进程通过命令行或任何其他方式。如何将句柄传递给子进程

我该怎么做? 如何从孩子接入互斥体?

这是我如何创建子进程:

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)铸造可以吗?

回答

5

两个选项:

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

    缺点是名称选择。如果你有名字冲突,你可能会得到不可预知的结果。攻击者可以使用相同的名称创建互斥锁,并创建拒绝服务情况。处理这个问题的一种方法是随机生成名称。例如,方法A可以生成用于名称的GUID,然后传递该GUID(字符串)在命令行上以处理B.

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

该技术没有与命名对象技术相同的缺点。

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

#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; 
} 
+0

对于已命名的互斥锁。他们是明显的解决方案。通过命令行传递一个GUID以避免碰撞是矫枉过正的:只需在每个程序中对其进行硬编码:无论如何它们都是唯一的。 –

+0

“子进程然后可以将命令行字符串转换回一个值,并简单地开始使用它”您的意思是将其转换为字符串? – Caio

+0

@Serge - appTranslator:对名称进行硬编码有两个问题。 (1)它将您限制为您的应用程序的单个实例。 (2)如果攻击者在您之前创建了互斥体(如我的答案中所述),则拒绝服务漏洞。 –

-1

您应该为此目标执行IPC(interporcess通信)。有在Windows IPC许多方法,如:

  1. 剪贴板
  2. COM
  3. RPC
  4. DataCopy
  5. ...

this article in MSD N代表的更多细节。

+0

我希望列表是随机的顺序,并没有按照推荐排序:) – user786653

+0

@ user786653:当然是! – hsalimi

1

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

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

+0

这不起作用。您不能将HANDLE序列化为字符串并将其传递给孩子。我试图做到这一点,但它不起作用。随意通过一个实例来证明我错了。 – jcoffland

+0

@jcoffland确定你可以,但你确实需要复制它,但根据答案 –

相关问题