南京专业网站设计公司价格做营销网站视频
news/
2025/10/9 3:51:38/
文章来源:
南京专业网站设计公司价格,做营销网站视频,北京建站模板系统,中国十大热门网站初级代码游戏的专栏介绍与文章目录-CSDN博客 程序长时间运行#xff0c;内存泄漏#xff0c;最后崩溃#xff0c;怎么办#xff1f; 程序24小时运行#xff0c;偶发随机崩溃#xff0c;怎么办#xff1f; 啃代码、内存泄漏检查工具、分析线程交互……没人敢承诺解决问题…初级代码游戏的专栏介绍与文章目录-CSDN博客 程序长时间运行内存泄漏最后崩溃怎么办 程序24小时运行偶发随机崩溃怎么办 啃代码、内存泄漏检查工具、分析线程交互……没人敢承诺解决问题。 那怎么办呢上标准工业级解决方案啊自动重启
目录
一、自动重启的原理
二、自动重启的实现
三、相关知识点
3.1 CommandLineToArg
3.2 LocalFree 3.3 OpenProcess 3.4 WaitForSingleObject 3.5 GetExitCodeProcess
3.6 GetModuleFileName
3.7 GetStartupInfo
3.8 CreateProcess 一、自动重启的原理 我不知道为什么很多程序员觉得自动重启很low就像我始终不明白为什么有些人一听见我说“重新编译一下”就笑难道不是重新编译一下大部分问题就解决了吗 自动重启原理很简单用一个进程监控另一个进程挂了就再启动一个。细节也不算多主要是正确判断进程状态和启动方式其实最大的工作量是程序恢复时应该如何回到原来的状态这意味着程序要随时保存状态。 只要你能做到用户无感你在背后做了什么用户在意吗
二、自动重启的实现 如果是UNIX用fork然后监控子进程挂了就再fork一个循环就解决问题了。 windows上麻烦一些监控进程控制台程序
#include stdafx.h
#include shellapi.h
#include stdio.h
#include stringusing namespace std;bool bDebug false;int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPWSTR lpCmdLine,_In_ int nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);// TODO: 在此处放置代码。if (bDebug)MessageBox(NULL, lpCmdLine, TEXT(启动), 0);wchar_t buf[256];DWORD pid 0;{LPWSTR* szArglist;int nArgs;int i;//从命令行获取要监控的进程的PID参数-pid后的下一个参数szArglist CommandLineToArgvW(lpCmdLine, nArgs);//注意如果没有参数会返回程序名如果有参数则不包括程序名或许是个BUGif (NULL szArglist){MessageBox(NULL, lpCmdLine, TEXT(CommandLineToArgvW失败), 0);return 0;}else{wsprintf(buf, TEXT(参数个数%d), nArgs);if (bDebug)MessageBox(NULL, buf, TEXT(), 0);for (i 0; i nArgs; i){if (bDebug)MessageBox(NULL, szArglist[i], TEXT(CommandLineToArgvW), 0);if (0 _tcsicmp(szArglist[i], TEXT(-pid)) i 1 nArgs){pid _wtol(szArglist[i 1]);wsprintf(buf, TEXT(%u), pid);if (bDebug)MessageBox(NULL, buf, szArglist[i 1], 0);}}}LocalFree(szArglist);}wsprintf(buf, TEXT(%u), pid);if (bDebug)MessageBox(NULL, buf, TEXT(pid), 0);//打开进程以供监控HANDLE handle OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, pid);//等待进程结束DWORD state WaitForSingleObject(handle, INFINITE);if (WAIT_OBJECT_0 state){DWORD exitCode;if (!GetExitCodeProcess(handle, exitCode))//获得退出码{MessageBox(NULL, TEXT(GetExitCodeProcess 出错), TEXT(未能获取程序结束状态), 0);}wsprintf(buf, TEXT(退出码 %u), exitCode);//MessageBox(NULL, buf, TEXT(任务完成), 0);if (0 ! exitCode)//正常退出是返回码return 返回码 或者exit(返回码)一般约定正常返回0异常结束肯定是非0{//这一段就是以-r参数重启程序两个程序必须在同一目录下wchar_t _app_pathname[MAX_PATH];GetModuleFileName(NULL, _app_pathname, MAX_PATH);wstring app_pathname _app_pathname;size_t pos app_pathname.find_last_of(\\);if (pos ! app_pathname.npos){app_pathname.erase(pos 1);app_pathname TEXT(app.exe);}else{app_pathname TEXT(app.exe);}wchar_t szCmdLine[256];wsprintf(szCmdLine, TEXT( -r));PROCESS_INFORMATION info;STARTUPINFO startup;GetStartupInfo(startup);BOOL bSucc CreateProcess(app_pathname.c_str(), szCmdLine, NULL, NULL,FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, startup, info);if (!bSucc){MessageBox(NULL, TEXT(CreateProcess 出错), TEXT(恢复程序失败), 0);}}}else if (WAIT_FAILED state){MessageBox(NULL, lpCmdLine, TEXT(WaitForSingleObject失败), 0);}else{MessageBox(NULL, lpCmdLine, TEXT(WaitForSingleObject非预期的返回值), 0);}return 0;
}这个程序是这样的工作的主程序名叫“app.exe”在适当的时候启动了监控进程就是这个代码名称任意但是必须和app.exe放在一起并把自己的pid传递给监控进程命令行参数-pid 主进程监控进程启动后从命令行获取到需要监控的pid监视pid状态如果是正常结束就退出程序如果是异常结束以“-r”参数启动主进程。 主进程启动过程是这样的启动到某个阶段检查命令行带有“-r”参数说明是自动恢复走自动恢复流程否则走正常流程启动监控进程并把自己的pid传递过去。 为什么要做一个独立的监控程序不用主进程自身呢因为程序太大了有很多静态初始化的话不知道起两个会不会有什么问题。 为什么要通过命令行参数传递进程PID呢主进程起子进程不是可以获得子进程的PID吗因为好多程序喜欢套壳啊返回的子进程又创建子进程干活自己马上就退出了。 获取自身PID的方法 DWORD pid GetCurrentProcessId();要在验证程序异常退出可以return一个非零值或者调用abort()。如果不区分是否是重启则不用处理参数启动监控进程的代码和监控进程启动主进程的相似。
三、相关知识点
3.1 CommandLineToArg win32程序处理命令行真是费劲死了。
shellapi.h
Shell32.dll/Shell32.libLPWSTR * CommandLineToArgvW([in] LPCWSTR lpCmdLine,[out] int *pNumArgs
); 注意参数pNumArgs是在函数内部分配的要在外部释放。这是C的习惯性做法。
3.2 LocalFree 释放本地内存对象。
HLOCAL LocalFree([in] _Frees_ptr_opt_ HLOCAL hMem
); 3.3 OpenProcess 打开进程对象以便后续等待进程结束。
HANDLE OpenProcess([in] DWORD dwDesiredAccess,[in] BOOL bInheritHandle,[in] DWORD dwProcessId
); 3.4 WaitForSingleObject 等待对象可以是进程、线程、控制台输入等类型的句柄等待的事件包括信号、超时等发生了某种事件函数就会返回。
DWORD WaitForSingleObject([in] HANDLE hHandle,[in] DWORD dwMilliseconds
); 3.5 GetExitCodeProcess 获得进程退出码。
BOOL GetExitCodeProcess([in] HANDLE hProcess,[out] LPDWORD lpExitCode
);
3.6 GetModuleFileName 一般用来获取程序的完整路径名。
DWORD GetModuleFileNameA([in, optional] HMODULE hModule,[out] LPSTR lpFilename,[in] DWORD nSize
);
3.7 GetStartupInfo 获得程序的启动信息在这个代码里用来传递给新进程。
void GetStartupInfoW([out] LPSTARTUPINFOW lpStartupInfo
);
3.8 CreateProcess 创建进程。
BOOL CreateProcessA([in, optional] LPCSTR lpApplicationName,[in, out, optional] LPSTR lpCommandLine,[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,[in] BOOL bInheritHandles,[in] DWORD dwCreationFlags,[in, optional] LPVOID lpEnvironment,[in, optional] LPCSTR lpCurrentDirectory,[in] LPSTARTUPINFOA lpStartupInfo,[out] LPPROCESS_INFORMATION lpProcessInformation
); 参数虽多大部分都可以不用。 这里是文档结束
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/932170.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!