关于思路的问题

时间:2022-03-29 00:23:17
老大让我做了一个心跳防护程序,就是一个服务可以防护很多程序,当防护的程序被意外关闭什么服务可以把它重新启动,是通过共享内存来实现服务和程序的通信的。
中间有一段的思路是这样的:
一个服务可以防护多个程序。
每多防护一个程序服务会启动三个线程和三个共享内存来进行通信。
开始时当程序被关闭重启后会被当做新的程序来进行防护,也就是启动新的线程和开辟新的共享内存。
我当时感觉这样会浪费资源,而且我怕原先的线程资源和内存得不到完全释放,在不断的重启中会一直增加内存消耗,还得一直分配新的内存,于是我想了一个方法:
       就是:1,服务启动时先向一个共享内存放入一个编号
                    2,第一个程序启动时先去内存读取这个编号,根据这个编号来进行共享内存分配,然后将这个编号存入对应自己名字的一个文件
                    3,其实程序启动时先去读取这个文件,如果不存在这个文件再去内存读取编号
                    4,当文件存在的话,也就是不是第一次启动,就直接根据这个编号去通过对应的原先的共享内存来和服务通信被防护。
                    5,当服务启动时会先去删除这些文件,来防止编号的混乱。
                    6,这样就可以在程序重启后还用原来的线程,原来的共享内存

然后我老大说尽量这个尽量不要进行I/O操作会存在风险,说我这个太复杂容易出错,这个服务逻辑应该越简单越好,就应该在程序重启后把它当成新的程序来防护,只要将线程资源和内存资源释放做好就行了

而且他也让我上网问问我这个方法到底可行不,会不会提高风险,请大家来指点一下,写得有点多,先谢谢了!

8 个解决方案

#1


有人来指点一下吗,是不是写得太多了都没耐心看完啊

#2


果然没人么。。。。

#3


为什么要搞心跳防护?因为被检测进程不时心脏停跳。
为什么被检测进程不时心脏停跳?因为被检测进程亚健康。
怎么知道被检测进程亚健康的原因:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!

根治了被检测进程亚健康→被检测进程不再心脏停跳→不用再搞心跳防护。
越依赖心跳防护→被检测进程心脏停跳越频繁→被检测进程越不健康!

怎么心跳防护“用来心跳防护不健康进程C”的进程B的不健康?
怎么心跳防护“用来心跳防护‘用来心跳防护不健康进程C”的进程B’的进程A”的不健康?

#4


还不如都向一个模块使用socket发心跳

#6


引用 3 楼 zhao4zhong1 的回复:
为什么要搞心跳防护?因为被检测进程不时心脏停跳。
为什么被检测进程不时心脏停跳?因为被检测进程亚健康。
怎么知道被检测进程亚健康的原因:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!

根治了被检测进程亚健康→被检测进程不再心脏停跳→不用再搞心跳防护。
越依赖心跳防护→被检测进程心脏停跳越频繁→被检测进程越不健康!

怎么心跳防护“用来心跳防护不健康进程C”的进程B的不健康?
怎么心跳防护“用来心跳防护‘用来心跳防护不健康进程C”的进程B’的进程A”的不健康?

赵老师,我刚开始编程,写这个目前就是在练手,我现在就想知道我写得那个1,2,3,4那个方法可行么?会不会提高风险?还是说那个红字标注的那种方法好

#7


奉劝楼主实际动手编程之前先通读《Windows核心编程》及其提供的随书代码。

#8


如果楼主执意不回头是岸,参考下面:
// ProcessManger.cpp: implementation of	the	CProcessManger class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "../sgateway.h"
#include "ProcessManger.h"
#include "../psapi/psapi.h"
#pragma comment( lib, "psapi" )

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CProcessManger g_pm;
CProcessManger::CProcessManger()
{
m_confile=_T("ProceData.dat");
m_listMonitor.RemoveAll();
memset(m_Err,0,1024);
}

CProcessManger::~CProcessManger()
{

}

int CProcessManger::FindIsResponding(MON_STRUCT &mon)
{
DWORD ExitCode;
  // WaitForSingleObject(hProcess, 5000L);
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_ALL_ACCESS,
FALSE,
mon.nPid );
if( NULL != hProcess )
{
FILETIME   l_Createtime,l_ExitTime,l_KernelTime,lpUserTime;
GetProcessTimes(hProcess,&l_Createtime,&l_ExitTime,&l_KernelTime,&lpUserTime);
if (mon.iKernelTime==l_KernelTime.dwLowDateTime)
{ //如果所监视的程序连续5次
mon.nNoResopTimes++;
if (mon.nNoResopTimes==5)
{
mon.nNoResopTimes=0;
mon.bMustRebootNow=1;//设置重启动标志
}
else  //进程反应正常,刚状态清0
{
mon.bMustRebootNow=0;
mon.nNoResopTimes=0;
}
}
else
{
mon.iKernelTime=l_KernelTime.dwLowDateTime;
}
DWORD dwResult;
BOOL fResponding = SendMessageTimeout(HWND_BROADCAST,WM_NULL,0,0,SMTO_ABORTIFHUNG,100,&dwResult);
if(!fResponding)
{
CloseHandle(hProcess);
return 1;
}
// LPDWORD lpExitCode;
int i_Ret=GetExitCodeProcess( hProcess, &ExitCode  );
if (i_Ret==0)
{
strcpy(m_Err,"得到程序状态失败!");
CloseHandle(hProcess);
return 1;
}
else
{
if (ExitCode!=STILL_ACTIVE)
{
CloseHandle(hProcess);
strcpy(m_Err,"程序已经死掉了!");
return 1;
}
else
{
CloseHandle(hProcess);
return 0;
}
}
}  //endif (NULL)
else
{
CloseHandle(hProcess);
return 0;
}
CloseHandle(hProcess);
return 3;
}

CString CProcessManger::GetProcessBaseModuleName(DWORD idProcess)
{
CString sName;

HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
idProcess );
if( NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;

if( EnumProcessModules( hProcess, &hMod, sizeof( hMod ), &cbNeeded ) )
{
DWORD dw = GetModuleBaseName( hProcess, hMod, sName.GetBuffer( MAX_PATH ), MAX_PATH );
sName.ReleaseBuffer();
}

CloseHandle( hProcess );
}

return( sName );
}

DWORD CProcessManger::GetProcessIDs(DWORD *pdwBuffer, DWORD dwSizeBuffer)
{
// Get the list of process IDs

DWORD cbNeeded = 0;

if( !EnumProcesses( pdwBuffer, dwSizeBuffer, &cbNeeded ) )
{
ASSERT( FALSE );
return( 0 );
}

return( cbNeeded / sizeof( DWORD ) );
}

CString CProcessManger::GetProcessPath(DWORD idProcess)
{
CString sPath;

HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
idProcess );
if( NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;

if( EnumProcessModules( hProcess, &hMod, sizeof( hMod ), &cbNeeded ) )
{
DWORD dw = GetModuleFileNameEx( hProcess, hMod, sPath.GetBuffer( MAX_PATH ), MAX_PATH );
sPath.ReleaseBuffer();
}

CloseHandle( hProcess );
}

return( sPath );
}

void CProcessManger::TerminateProcessID(DWORD id)
{
HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, id );

if( NULL != hProcess )
{
TerminateProcess( hProcess, 0 );
CloseHandle( hProcess );
}
}


BOOL CProcessManger::CheckMonitor()
{
int size=m_listMonitor.GetSize();
if (size<=0) {
strcpy(m_Err,"没有要监视的文件");
return FALSE;
}
int index=-1;
MON_STRUCT mon;
int i_ReturnCode=0;
try
{
for (index=0;index<size;index++) {
mon=m_listMonitor.GetAt(index);
mon.nPid=IsFileInList(mon.sExepath);
if (mon.nPid!=0) {
i_ReturnCode=FindIsResponding(mon);
if (i_ReturnCode!=0) {
mon.bMustRebootNow=1;
mon.iCurrStatus=4;
}
} else {
mon.bMustRebootNow=1;
mon.iCurrStatus=3;
}
m_listMonitor.SetAt(index,mon);
CheckExeApp();
}

}
catch(...)
{
return FALSE;
}
return TRUE;
}

//查询一下程序是否正常运行,如果不正常,则杀死进程并安设置重新启动进程
void CProcessManger::CheckExeApp()
{
int size=m_listMonitor.GetSize();
MON_STRUCT mon;
for (int i=0;i<size;i++) {
mon=m_listMonitor.GetAt(i);
if (mon.bMustRebootNow==1) {
//检查程序没有返回需要重新启动时
//如果进程存在,则杀死进程
if (mon.nPid!=-1) TerminateProcessID(mon.nPid);
//重新启动进程
WinExec(mon.sExepath,SW_SHOWDEFAULT);
if (mon.iCurrStatus==4) {
g_log.print("程序[%s]无响应,重新启动!",mon.sExepath);
} else {
g_log.print("程序[%s]未启动,重新启动!",mon.sExepath);
}
mon.bInProcList=0;
mon.bMustRebootNow=0;
mon.iKernelTime=0;
mon.nNoResopTimes=0;
mon.iCurrStatus=0;
mon.nPid=-1;
m_listMonitor.SetAt(i,mon);
}

}
}

BOOL CProcessManger::AddMonData(LPCTSTR sExeFile, int type)
{
MON_STRUCT mon;
mon.iActType=type;
mon.iCurrStatus=0;
mon.iKernelTime=0;
mon.bMustRebootNow=-1;
mon.nPid=-1;
mon.bInProcList=0; //初始时列为不在进程表中
strcpy(mon.sExepath,sExeFile);
return m_listMonitor.Add(mon);
}

int CProcessManger::GetMonIndex(LPCTSTR sExeFile)
{
int size=m_listMonitor.GetSize();
if (size<=0) return -1;
for(int i=0;i<size;i++) {
if (strstr(sExeFile,m_listMonitor.GetAt(i).sExepath)!=NULL) {
return i;
}
}
return -1;
}

UINT CProcessManger::IsFileInList(LPCTSTR file)
{
    UINT pid=0;
    CString sFile=file;
    try
    {
        //// 创窗口的标示   1:表示窗口存在, 0:表示窗口不存在
        CString sName;
        DWORD cProcesses = GetProcessIDs( m_aProcesses, sizeof( m_aProcesses ) );
        for( DWORD idx = 0; idx < cProcesses; idx++ )
        {
            //得到进程的全路径名
            sName=GetProcessPath( m_aProcesses[ idx ] );
            if( sName.IsEmpty() )
            {
                continue;
            }
            sName.Replace("/","\\");
            sFile.Replace("/","\\");
            //TRACE("file=%s\n",sName);
            if (sName.CompareNoCase(sFile)==0) return m_aProcesses[ idx ];
        }

    }
    catch(...)
    {
        return 0;
    }
    return 0;
}


void CProcessManger::LoadData()
{
    CFile fp;
    if (!fp.Open(g_AppPath+m_confile,CFile::modeRead)) return;
    MON_STRUCT stmp;
    m_listMonitor.RemoveAll();
    while (1) {
        if (fp.Read(&stmp,sizeof(MON_STRUCT))<=0) break;
        m_listMonitor.Add(stmp);
    }
    fp.Close();
}

void CProcessManger::SaveData()
{
        //ini内容装入结束
    int size=m_listMonitor.GetSize();
    if (size<=0) return;
    CFile fp;
    if (!fp.Open(g_AppPath+m_confile,CFile::modeCreate|CFile::modeWrite)) return;
    for (int i=0;i<size;i++) {
        fp.Write(&m_listMonitor.GetAt(i),sizeof(MON_STRUCT));
    }
    fp.Close();
}

#1


有人来指点一下吗,是不是写得太多了都没耐心看完啊

#2


果然没人么。。。。

#3


为什么要搞心跳防护?因为被检测进程不时心脏停跳。
为什么被检测进程不时心脏停跳?因为被检测进程亚健康。
怎么知道被检测进程亚健康的原因:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!

根治了被检测进程亚健康→被检测进程不再心脏停跳→不用再搞心跳防护。
越依赖心跳防护→被检测进程心脏停跳越频繁→被检测进程越不健康!

怎么心跳防护“用来心跳防护不健康进程C”的进程B的不健康?
怎么心跳防护“用来心跳防护‘用来心跳防护不健康进程C”的进程B’的进程A”的不健康?

#4


还不如都向一个模块使用socket发心跳

#5


#6


引用 3 楼 zhao4zhong1 的回复:
为什么要搞心跳防护?因为被检测进程不时心脏停跳。
为什么被检测进程不时心脏停跳?因为被检测进程亚健康。
怎么知道被检测进程亚健康的原因:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!

根治了被检测进程亚健康→被检测进程不再心脏停跳→不用再搞心跳防护。
越依赖心跳防护→被检测进程心脏停跳越频繁→被检测进程越不健康!

怎么心跳防护“用来心跳防护不健康进程C”的进程B的不健康?
怎么心跳防护“用来心跳防护‘用来心跳防护不健康进程C”的进程B’的进程A”的不健康?

赵老师,我刚开始编程,写这个目前就是在练手,我现在就想知道我写得那个1,2,3,4那个方法可行么?会不会提高风险?还是说那个红字标注的那种方法好

#7


奉劝楼主实际动手编程之前先通读《Windows核心编程》及其提供的随书代码。

#8


如果楼主执意不回头是岸,参考下面:
// ProcessManger.cpp: implementation of	the	CProcessManger class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "../sgateway.h"
#include "ProcessManger.h"
#include "../psapi/psapi.h"
#pragma comment( lib, "psapi" )

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CProcessManger g_pm;
CProcessManger::CProcessManger()
{
m_confile=_T("ProceData.dat");
m_listMonitor.RemoveAll();
memset(m_Err,0,1024);
}

CProcessManger::~CProcessManger()
{

}

int CProcessManger::FindIsResponding(MON_STRUCT &mon)
{
DWORD ExitCode;
  // WaitForSingleObject(hProcess, 5000L);
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_ALL_ACCESS,
FALSE,
mon.nPid );
if( NULL != hProcess )
{
FILETIME   l_Createtime,l_ExitTime,l_KernelTime,lpUserTime;
GetProcessTimes(hProcess,&l_Createtime,&l_ExitTime,&l_KernelTime,&lpUserTime);
if (mon.iKernelTime==l_KernelTime.dwLowDateTime)
{ //如果所监视的程序连续5次
mon.nNoResopTimes++;
if (mon.nNoResopTimes==5)
{
mon.nNoResopTimes=0;
mon.bMustRebootNow=1;//设置重启动标志
}
else  //进程反应正常,刚状态清0
{
mon.bMustRebootNow=0;
mon.nNoResopTimes=0;
}
}
else
{
mon.iKernelTime=l_KernelTime.dwLowDateTime;
}
DWORD dwResult;
BOOL fResponding = SendMessageTimeout(HWND_BROADCAST,WM_NULL,0,0,SMTO_ABORTIFHUNG,100,&dwResult);
if(!fResponding)
{
CloseHandle(hProcess);
return 1;
}
// LPDWORD lpExitCode;
int i_Ret=GetExitCodeProcess( hProcess, &ExitCode  );
if (i_Ret==0)
{
strcpy(m_Err,"得到程序状态失败!");
CloseHandle(hProcess);
return 1;
}
else
{
if (ExitCode!=STILL_ACTIVE)
{
CloseHandle(hProcess);
strcpy(m_Err,"程序已经死掉了!");
return 1;
}
else
{
CloseHandle(hProcess);
return 0;
}
}
}  //endif (NULL)
else
{
CloseHandle(hProcess);
return 0;
}
CloseHandle(hProcess);
return 3;
}

CString CProcessManger::GetProcessBaseModuleName(DWORD idProcess)
{
CString sName;

HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
idProcess );
if( NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;

if( EnumProcessModules( hProcess, &hMod, sizeof( hMod ), &cbNeeded ) )
{
DWORD dw = GetModuleBaseName( hProcess, hMod, sName.GetBuffer( MAX_PATH ), MAX_PATH );
sName.ReleaseBuffer();
}

CloseHandle( hProcess );
}

return( sName );
}

DWORD CProcessManger::GetProcessIDs(DWORD *pdwBuffer, DWORD dwSizeBuffer)
{
// Get the list of process IDs

DWORD cbNeeded = 0;

if( !EnumProcesses( pdwBuffer, dwSizeBuffer, &cbNeeded ) )
{
ASSERT( FALSE );
return( 0 );
}

return( cbNeeded / sizeof( DWORD ) );
}

CString CProcessManger::GetProcessPath(DWORD idProcess)
{
CString sPath;

HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
idProcess );
if( NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;

if( EnumProcessModules( hProcess, &hMod, sizeof( hMod ), &cbNeeded ) )
{
DWORD dw = GetModuleFileNameEx( hProcess, hMod, sPath.GetBuffer( MAX_PATH ), MAX_PATH );
sPath.ReleaseBuffer();
}

CloseHandle( hProcess );
}

return( sPath );
}

void CProcessManger::TerminateProcessID(DWORD id)
{
HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, id );

if( NULL != hProcess )
{
TerminateProcess( hProcess, 0 );
CloseHandle( hProcess );
}
}


BOOL CProcessManger::CheckMonitor()
{
int size=m_listMonitor.GetSize();
if (size<=0) {
strcpy(m_Err,"没有要监视的文件");
return FALSE;
}
int index=-1;
MON_STRUCT mon;
int i_ReturnCode=0;
try
{
for (index=0;index<size;index++) {
mon=m_listMonitor.GetAt(index);
mon.nPid=IsFileInList(mon.sExepath);
if (mon.nPid!=0) {
i_ReturnCode=FindIsResponding(mon);
if (i_ReturnCode!=0) {
mon.bMustRebootNow=1;
mon.iCurrStatus=4;
}
} else {
mon.bMustRebootNow=1;
mon.iCurrStatus=3;
}
m_listMonitor.SetAt(index,mon);
CheckExeApp();
}

}
catch(...)
{
return FALSE;
}
return TRUE;
}

//查询一下程序是否正常运行,如果不正常,则杀死进程并安设置重新启动进程
void CProcessManger::CheckExeApp()
{
int size=m_listMonitor.GetSize();
MON_STRUCT mon;
for (int i=0;i<size;i++) {
mon=m_listMonitor.GetAt(i);
if (mon.bMustRebootNow==1) {
//检查程序没有返回需要重新启动时
//如果进程存在,则杀死进程
if (mon.nPid!=-1) TerminateProcessID(mon.nPid);
//重新启动进程
WinExec(mon.sExepath,SW_SHOWDEFAULT);
if (mon.iCurrStatus==4) {
g_log.print("程序[%s]无响应,重新启动!",mon.sExepath);
} else {
g_log.print("程序[%s]未启动,重新启动!",mon.sExepath);
}
mon.bInProcList=0;
mon.bMustRebootNow=0;
mon.iKernelTime=0;
mon.nNoResopTimes=0;
mon.iCurrStatus=0;
mon.nPid=-1;
m_listMonitor.SetAt(i,mon);
}

}
}

BOOL CProcessManger::AddMonData(LPCTSTR sExeFile, int type)
{
MON_STRUCT mon;
mon.iActType=type;
mon.iCurrStatus=0;
mon.iKernelTime=0;
mon.bMustRebootNow=-1;
mon.nPid=-1;
mon.bInProcList=0; //初始时列为不在进程表中
strcpy(mon.sExepath,sExeFile);
return m_listMonitor.Add(mon);
}

int CProcessManger::GetMonIndex(LPCTSTR sExeFile)
{
int size=m_listMonitor.GetSize();
if (size<=0) return -1;
for(int i=0;i<size;i++) {
if (strstr(sExeFile,m_listMonitor.GetAt(i).sExepath)!=NULL) {
return i;
}
}
return -1;
}

UINT CProcessManger::IsFileInList(LPCTSTR file)
{
    UINT pid=0;
    CString sFile=file;
    try
    {
        //// 创窗口的标示   1:表示窗口存在, 0:表示窗口不存在
        CString sName;
        DWORD cProcesses = GetProcessIDs( m_aProcesses, sizeof( m_aProcesses ) );
        for( DWORD idx = 0; idx < cProcesses; idx++ )
        {
            //得到进程的全路径名
            sName=GetProcessPath( m_aProcesses[ idx ] );
            if( sName.IsEmpty() )
            {
                continue;
            }
            sName.Replace("/","\\");
            sFile.Replace("/","\\");
            //TRACE("file=%s\n",sName);
            if (sName.CompareNoCase(sFile)==0) return m_aProcesses[ idx ];
        }

    }
    catch(...)
    {
        return 0;
    }
    return 0;
}


void CProcessManger::LoadData()
{
    CFile fp;
    if (!fp.Open(g_AppPath+m_confile,CFile::modeRead)) return;
    MON_STRUCT stmp;
    m_listMonitor.RemoveAll();
    while (1) {
        if (fp.Read(&stmp,sizeof(MON_STRUCT))<=0) break;
        m_listMonitor.Add(stmp);
    }
    fp.Close();
}

void CProcessManger::SaveData()
{
        //ini内容装入结束
    int size=m_listMonitor.GetSize();
    if (size<=0) return;
    CFile fp;
    if (!fp.Open(g_AppPath+m_confile,CFile::modeCreate|CFile::modeWrite)) return;
    for (int i=0;i<size;i++) {
        fp.Write(&m_listMonitor.GetAt(i),sizeof(MON_STRUCT));
    }
    fp.Close();
}