📄 csdn
字号:
PADDING-TOP: 0px;
FONT-FAMILY: Verdana, Arial
}
PRE.bhw98
{
FONT-SIZE: 9pt;
PADDING-RIGHT: 5px;
PADDING-LEFT: 5px;
PADDING-BOTTOM: 5px;
MARGIN: 5px 0px;
LINE-HEIGHT: normal;
PADDING-TOP: 5px;
BACKGROUND-COLOR: #f0f0f0
}
PRE.diag
{
FONT-SIZE: 9pt;
PADDING-RIGHT: 5px;
PADDING-LEFT: 5px;
PADDING-BOTTOM: 5px;
MARGIN: 5px 0px;
LINE-HEIGHT: normal;
PADDING-TOP: 5px;
}
CODE.bhw98
{
FONT-SIZE: 9pt;
COLOR: #000000
}
TABLE.bhw98
{
BORDER-RIGHT: #808080 1px solid;
BORDER-TOP: #808080 1px solid;
FONT-SIZE: 9pt;
MARGIN: 3px 0px 10px;
BORDER-LEFT: #808080 1px solid;
LINE-HEIGHT: normal;
BORDER-BOTTOM: #808080 1px solid;
FONT-FAMILY: Verdana, Arial
}
TD.bhw98
{
BORDER-RIGHT: darkgray 1px solid;
PADDING-RIGHT: 10px;
BORDER-TOP: darkgray 1px solid;
PADDING-LEFT: 5px;
FONT-SIZE: 9pt;
PADDING-BOTTOM: 0px;
MARGIN: 0px;
BORDER-LEFT: darkgray 1px solid;
LINE-HEIGHT: normal;
PADDING-TOP: 3px;
BORDER-BOTTOM: darkgray 1px solid;
FONT-FAMILY: Verdana, Arial;
BACKGROUND-COLOR: #f0f0f0
}
STRONG.bhw98
{
FONT-WEIGHT: bolder;
FONT-SIZE: 20pt;
COLOR: #228b22;
FONT-STYLE: italic;
FONT-FAMILY: Verdana, Arial
}
LI.bhw98
{
FONT-SIZE: 9pt;
MARGIN: 3px 0px 0px 3px;
LINE-HEIGHT: normal;
FONT-FAMILY: Verdana, Arial
}
H1.bhw98
{
MARGIN-TOP: 25px;
FONT-WEIGHT: bolder;
FONT-SIZE: 12pt;
MARGIN-BOTTOM: 5px;
LINE-HEIGHT: normal;
FONT-FAMILY: Verdana, Arial
}
H2.bhw98
{
MARGIN-TOP: 20px;
FONT-WEIGHT: bolder;
FONT-SIZE: 10.5pt;
MARGIN-BOTTOM: 5px;
LINE-HEIGHT: normal;
FONT-FAMILY: Verdana, Arial
}
H3.bhw98
{
MARGIN-TOP: 15px;
FONT-WEIGHT: bolder;
FONT-SIZE: 9pt;
MARGIN-BOTTOM: 5px;
LINE-HEIGHT: normal;
FONT-FAMILY: Verdana, Arial
}
SPAN.key
{
COLOR: #0000ff
}
SPAN.num
{
COLOR: #800000
}
SPAN.str
{
COLOR: #8b008b
}
SPAN.rem
{
COLOR: #008000
}
</STYLE>
<P class=bhw98>相信大多数的程序员或用户,在Windows中见到类似于下面的亲切而又温馨的提示信息,都不会感到陌生:</P>
<P class=bhw98>“XXX执行了非法操作,将被关闭。要终止程序,请单击<确定>;要调试程序,请单击<取消>。”或者,“是否向Microsoft发送错误报告?<发送>,<不发送>。”</P>
<P class=bhw98>如果这个程序运行在无人值守、需要保持连续工作状态的场合,而其中的bug又一时难以排除,就需要采取应急措施,消除或减少程序出错造成的影响。本文讨论解决这个问题的办法。</P>
<P class=bhw98>做过一定硬件开发的人都知道,恶劣的工作环境,带有缺陷的硬件设计,不完善的算法等内外因素,都可能造成程序“跑飞”,因此专门加装一个“看门狗”,负责监视程序主体,必要时产生复位中断,有效地避免设备当机。</P>
<P class=bhw98>“看门狗”的思想,完全可以拿到高级语言编程中来用。基本做法是:设计一个简单的监视程序做为主进程,将原来的工作程序作为子进程,由主进程启动子进程并监视子进程的运行状态。子进程在发生严重错误时不弹出本文开始时描述的对话框,而是悄悄退出。主进程发现子进程退出后,重新启动子进程。如此反复。</P>
<P class=bhw98>在具体实现上,下面以VC为例说明:</P>
<H3>设置子进程为“静默模式”</H3>
<P class=bhw98>在系统初始化部分(CWinApp或main中的开头),调用API函数SetErrorMode</P>
<PRE class=bhw98>SetErrorMode(SEM_NOGPFAULTERRORBOX);</PRE>
<P class=bhw98>保证程序在发生严重错误时不弹出对话框,无需人工干预,自行退出。</P>
<H3>启动子进程</H3>
<P class=bhw98>在主进程中,创建子进程并运行。假定子进程的可执行文件为work.exe,示意性代码如下</P>
<PRE class=bhw98>STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &pi, sizeof(pi) );
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
// Start the child process
if (CreateProcess("work.exe", "", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
// success
… …
}
</PRE>
<P class=bhw98>CreateProcess有10个参数,看起来挺吓人,其实并不复杂,很容易理解。最后一个参数会返回子进程的ID和句柄等信息,后面就是对进程ID或句柄进行监视。</P>
<H3>监视子进程</H3>
<P class=bhw98>定时检查子进程是否在正常运行。有好几个API都可以用于对指定ID的进程进行监视,象GetProcessVersion,GetProcessTimes,GetProcessIoCounters等,其中GetProcessVersion最简单,只有一个参数:</P>
<PRE class=bhw98>DWORD GetProcessVersion( DWORD ProcessId);</PRE>
<P class=bhw98>当子进程已经退出时,该函数返回0。
<P class=bhw98>更为“专业”的函数是GetExitCodeProcess,它甚至能告诉我们子进程退出的原因:</P>
<PRE class=bhw98>BOOL GetExitCodeProcess(
HANDLE hProcess, // handle to the process
LPDWORD lpExitCode // termination status
);
</PRE>
<H3>更进一步的考虑</H3>
<P class=bhw98>为增强系统的可靠性,给工作程序加装“看门狗”,不失为一种可行的技术方案。但如果有两套用户界面,看起来就有点不那么专业了。可将子进程设计为基于console的应用,不带用户界面,所有的信息都通过主进程窗口输出。主进程CreateProcess的第6个参数需加入CREATE_NO_WINDOW项,将子进程隐藏起来。这样从用户的角度看起来,就象只存在一个应用程序。</P>
<P class=bhw98>另一个问题是,如果用户关闭主进程,如何同时关闭子进程?用TerminateProcess函数固然能结束子进程,但可能会造成内存泄漏等新问题。最好是主进程向子进程发出结束的消息并进行同步,使子进程能够从容地退出。</P>
<P class=bhw98>再扩展一下,一个主进程可以同时管理多个子进程。典型的例子是利用多块网卡进行抓包、分析、处理的系统,将每一块网卡应用与一个子进程绑定,而主进程负责监视所有的子进程的工作。</P>
<P class=bhw98>上面的讨论涉及到进程间通信(IPC)问题。解决的办法有很多,象file mapping, mailslot, pipe, DDE, COM, RPC, clipboard, socket, WM_COPYDATA等都能达到目的,可根据个人喜好和具体情况采用。</P>
<H2 class=bhw98>[相关资源]</H2>
<LI class=bhw98>科脑工作室(Kernel Studio):<A href="http://www.kernelstudio.com">www.kernelstudio.com</A>
<HR>
<P class=bhw98 align=right>发布日期: 2004-04-27
<P class=bhw98> </P></span>
<br />
<div style="font-size: 14px; line-height: 25px;"><strong>作者Blog:</strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/bhw98/" target="_blank">http://blog.csdn.net/bhw98/</a></div>
<div style="font-size: 14px; line-height: 25px; color:#900;"><strong>相关文章</strong></div>
<table id="ArticleContent1_ArticleContent1_RelatedArticles" cellspacing="0" border="0" style="border-collapse:collapse;">
<tr>
<td>
<a href="article/27/27281.shtm">给应用程序加装“看门狗”</a>
</td>
</tr><tr>
<td>
<a href="article/25/25700.shtm">“通过串口收发短消息”的Q&A汇编</a>
</td>
</tr><tr>
<td>
<a href="article/25/25263.shtm">用JScript实现公历到农历的日期转换</a>
</td>
</tr><tr>
<td>
<a href="article/24/24861.shtm">通过串口实时接收短消息</a>
</td>
</tr><tr>
<td>
<a href="article/23/23452.shtm">MSN Messenger协议概况</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<a name="#Comment"></a>
<table width="100%" border="0" cellpadding="0">
<tr>
<td>
<table cellSpacing=0 cellPadding=0 width="100%" align=center bgColor=#006699 border=0>
<tr bgColor=#006699>
<td id=white align=center width=556 bgColor=#006699>
<font color=#ffffff >对该文的评论</font> </td>
</tr>
</table>
<table border="0" cellpadding="2" cellspacing="1" width="100%" align="center" bgcolor="#666666">
<tr>
<td colspan="3" bgcolor="#cccccc">
<span style="color:#990000;">
<img src="/images/ico_pencil.gif" hspace="1" height="16" width="16">
</span>
<span id="CommnetList1_CommnetList1_rpCommentList__ctl0_lblUserName">xrenwu</span>
<i>(
<span id="CommnetList1_CommnetList1_rpCommentList__ctl0_lblPostTime">2004-05-02</span>)</i>
</td>
</tr>
<tr>
<td colspan="3" width="532" bgcolor="#ffffff">
<span id="CommnetList1_CommnetList1_rpCommentList__ctl0_lblContent">好!支持</span>
</td>
</tr>
</table>
<div align=right>
<a id="CommnetList1_CommnetList1_Morelink" href="http://comment.csdn.net/Comment.aspx?c=2&s=27281">【评论】</a>
<a id="CommnetList1_CommnetList1_Hyperlink1" href="javascript:window.close();">【关闭】</a>
</div>
<br>
</td>
</tr>
</table>
</TD>
</TR>
</TABLE>
</form>
<!-- 版权 -->
<hr width="770" noShade size="1" align="center">
<table cellspacing="0" cellpadding="0" width="500" border="0" align="center">
<tr>
<td valign="bottom" height="10" align="center">
<a href="http://www.csdn.net/intro/intro.asp?id=2">网站简介</a>
-
<a href="http://www.csdn.net/intro/intro.asp?id=5">广告服务</a>
-
<a href="http://www.csdn.net/map/map.shtm">网站地图</a>
-
<a href="http://www.csdn.net/help/help.asp">帮助信息</a>
-
<a href="http://www.csdn.net/intro/intro.asp?id=2">联系方式</a>
-
<a href="http://www.csdn.net/english">English</a>
</td>
<td align="center" rowspan="3"><a href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><img height="48" src="/images/biaoshi.gif" width="40" border="0"></a></td>
</tr>
<tr>
<td valign="top" align="center">北京百联美达美数码科技有限公司 版权所有 京ICP证020026号</td>
</tr>
<tr align="center">
<td valign="top"><font face="Verdana">Copyright © CSDN.NET, Inc. All Rights Reserved</font></td>
</tr>
<tr><td height="15"></td></tr>
</table>
<!-- /版权 -->
<script>
document.write("<img src=http://count.csdn.net/count/pageview1.asp?columnid=4&itemid=11 border=0 width=0 height=0>");
</script>
</body>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -