1. 程式人生 > >Windows下多程序的實現案例

Windows下多程序的實現案例

       最近碰到一個多程序的問題牽涉到了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);
		}
	}  
}