最近学习Windows进程控制相关的知识,发现一个以前没有注意到的问题:在多个进程共用一个控制台的时候,如果在某个时刻一起printf输出,那么输出的文字将会混合在一起。要解决这个问题,必须互斥的打印才行,在这里我使用互斥体来实现。
#include<windows.h>
#include<iostream>
static LPCTSTR Mutex_Name="aaa";
static LPCTSTR g_szContinueEvent="Continue";
void Count()//功能是两个进程交替地数数 数数间隔为3秒
{
HANDLE child_mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,Mutex_Name);
if(child_mutex!=NULL)
{
for(int i=0;i<5;i++){
WaitForSingleObject(child_mutex,INFINITE);//等待互斥锁释放 避免同一窗口下输出混合
Sleep(1000);
printf("processid:%d num:%d\n",GetCurrentProcessId(),i);
Sleep(3000);//注意sleep在等待与释放锁之间 否则刚释放锁另一个进程就打印 两个进程几乎同时输出
ReleaseMutex(child_mutex);//释放互斥锁给另一个进程 避免同一窗口下输出混合
}
}
}
//子进程才会调用
void SignalParent()
{
HANDLE hEventContinue=OpenEvent(
EVENT_MODIFY_STATE,
FALSE,
g_szContinueEvent);
if(hEventContinue!=NULL)
{
SetEvent(hEventContinue);
}
CloseHandle(hEventContinue);
}
BOOL CreateChild()
{
TCHAR szFilename[MAX_PATH];
GetModuleFileName(NULL,szFilename,MAX_PATH);//第一个参数为NULL获取当前程序路径
TCHAR szCmdLine[MAX_PATH];
sprintf(szCmdLine,"\"%s\" child",szFilename);
STARTUPINFO si;
ZeroMemory(reinterpret_cast<void*> (&si),sizeof(si));
si.cb=sizeof(si);
PROCESS_INFORMATION pi;
BOOL bCreateOK=CreateProcess(
szFilename,
szCmdLine,
NULL,
NULL,
FALSE,
0, //CREATE_NEW_CONSOLE 使得进程各自print时分开
NULL,
NULL,
&si,
&pi);
if(bCreateOK)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return(bCreateOK);
}
void WaitForChild()
{
//父进程创建事件
HANDLE hEventContinue=CreateEvent(
NULL,
TRUE,
FALSE,
g_szContinueEvent);
HANDLE mutex=CreateMutex(NULL,TRUE,Mutex_Name);//当前进程获得互斥锁
if(hEventContinue!=NULL)//如果创建事件成功
{
BOOL b1=CreateChild();
BOOL b2=CreateChild();
printf("Event Created.\n");
if(b1&&b2)//如果创建子进程成功
{
printf("ChildProcess Created.\n");
printf("Parent process waiting on child process.\n");
ReleaseMutex(mutex);
WaitForSingleObject(hEventContinue,INFINITE);//等待特定事件
printf("Parent process recieved the event signaling from child process.\n");
}
CloseHandle(mutex);
CloseHandle(hEventContinue);
}
}
int main(int argc,char* argv[]){
if(argc>1&&strcmp(argv[1],"child")==0){//子进程运行
Count();
SignalParent();
}
else//父进程运行
{
WaitForChild();
}
}
关于为什么会产生混合的情况,原因是printf是一个字符一个字符的输出,中间如果有其他内容也在输出,则会混乱。