最近碰到一个多进程的问题牵涉到了Windows下多进程的操作。经过研究也算是找到了一种解决方案。下面具体介绍一下这个题目中自己的收获。
背景介绍:程序涉及到Win32与Linux两个平台,要求同时启动多个进程,进程下面启动 多个线程。由于Windows的设计原理与Linux有很大区别(具体可参考Windows移植到Linux),因此Linux平台下创建多个进程比较容易实现。Windows下就比较困难。
下面是Linux下的代码:
rv = setpgid(0, 0);
if(rv == -1)
{
return rv;
}
for(i=0; i<uiDevNum; i++)
{
if((pids[i] = fork()) < 0)
{
uiForkErrorFlag = 1;
goto END;
}
else if(pids[i] == 0)
{
rv = Primary_Test(pucDevName[i], puiDevType[i]);
if(rv != SDR_OK)
{
return rv;
}
_exit(127);
}
else
{
//父进程
//子进程计数
uiChildProcNum++;
}
}
END:
if((uiForkErrorFlag == 1) && (uiChildProcNum > 0))
{
//终止其余子进程
for(i=0; i<uiChildProcNum; i++)
{
if(pids[i] != 0)
{
kill(pids[i], SIGTERM);
}
}
}
else if(uiChildProcNum > 0)
{
//等待子进程终止
pid_Termination = wait(NULL); //终止其余子进程
for(i=0; i<uiChildProcNum; i++)
{
if((pid_Termination == -1) || (pids[i] != pid_Termination))
{
kill(pids[i], SIGTERM);
}
}
}
如果按照这个思路写出Win32平台下的代码,首先根据CreatProcess的设计结构,在Windows下我们知道CreatProcess创建一个新的进程,这意味着不能像Linux一样创建的新进程执行本程序中的代码。否则会出现无限递归创建进程的情况,这是我们将需要执行的那段代码单独抽取出来,生成可执行文件,如果跟父进程有什么所需的参数,使用CreatProcess中的第二个参数传递进去。在父进程中通过每个子进程的handle监测每个子进程的执行情况。
for(i=0; i<uiDevNum; i++)
{
ZeroMemory( &si[i], sizeof(si[i]) );
si[i].cb = sizeof(si[i]);
ZeroMemory( &pi[i], sizeof(pi[i]) );
memset(strCmdLine, 0, sizeof(strCmdLine));
strcpy(strCmdLine, "Auto_EnumDevice_Product_Test_Sub.exe");
strcat(strCmdLine, " ");
strcat(strCmdLine, pucDevName[i]);
memset(strDevType, 0, sizeof(strDevType));
sprintf(strDevType, "%d", puiDevType[i]);
strcat(strCmdLine, " ");
strcat(strCmdLine, strDevType);
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line).
strCmdLine, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si[i], // Pointer to STARTUPINFO structure.
&pi[i] ) // Pointer to PROCESS_INFORMATION structure.
)
{
//创建子进程失败
uiForkErrorFlag = 1;
goto END;
}
//父进程
//子进程计数
uiChildProcNum++;
lpHandles[i] = pi[i].hProcess;
}
END:
if((uiForkErrorFlag == 1) && (uiChildProcNum > 0))
{
//终止其余子进程
for(i=0; i<uiChildProcNum; i++)
{
TerminateProcess(pi[i].hProcess, 127);
SLEEP(60);
CloseHandle(pi[i].hThread);
CloseHandle(pi[i].hProcess);
}
}
else if(uiChildProcNum > 0)
{
rv = WaitForMultipleObjects(uiChildProcNum, lpHandles, FALSE, INFINITE);
if((rv >= WAIT_OBJECT_0) && (rv <= WAIT_OBJECT_0 + uiChildProcNum - 1))
{
CloseHandle(pi[rv].hThread);
CloseHandle(pi[rv].hProcess);
} //终止其余子进程
for(i=0; i<uiChildProcNum; i++)
{
if(i != rv)
{
TerminateProcess(pi[i].hProcess, 127);
SLEEP(60);
CloseHandle(pi[i].hThread);
CloseHandle(pi[i].hProcess);
}
}
}