求思路,有点乱

hjl0508 2014-05-09 01:38:22
公司让我用c++写了一个心跳防护的东西,跟这个描述的一样,http://blog.csdn.net/happyparrot/article/details/1062501,动态链接库和防护程序。防护程序写成了服务,我进程间通信使用的共享内存,信号量的增减是都在服务中的两个线程中进行的,动态链接库用向共享内存中不断写入信号量来实现心跳。
现在我写的东西一个服务只能保护一个进程,而且stop函数没有参数,公司要求一个服务要能保护多个进程,还要
“终止心跳函数:StopHeartBeat(Bool AblStopService)
本函数用于正常终止被防护程序。参数AblStopService为ture时,同时会终止心跳恢复进程;为False则保持心跳恢复进程,只不再防护此被防护程序。”
我是刚开始从事开发,好多技术和思想都没接触过,没人带我,现在我的思路有点乱,感觉要改好多东西。。。。有没有谁做过类似的东西,给点思路
...全文
106 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
hjl0508 2014-05-09
  • 打赏
  • 举报
回复
没人了 啊。。。。
赵4老师 2014-05-09
  • 打赏
  • 举报
回复
ProcessManger.cpp
// 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();
}
赵4老师 2014-05-09
  • 打赏
  • 举报
回复
《Windows核心编程》 仅供参考 ProcessManger.h
// ProcessManger.h: interface for the CProcessManger class.
// 用途:进程管理,看某个进程如果死了重新启动之
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PROCESSMANGER_H__E49C1DBD_4E0B_4456_8CF1_5C6A712CB3E9__INCLUDED_)
#define AFX_PROCESSMANGER_H__E49C1DBD_4E0B_4456_8CF1_5C6A712CB3E9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
typedef struct tagMONSTRUCT{
    char sExepath[255];   //用来监视的文件名
    unsigned int iKernelTime; //监视文件的系统占用时间
    int iActType;         //对所监视文件处理方式   //0或1是否要重新运行
    int iCurrStatus;      //当前的运行状态   0 未运行 1 运行中
    int nNoResopTimes;    //没有响应的次数
    BOOL bMustRebootNow;  //-1 未知 0 运行良好 1 必需重启
    unsigned int nPid;    //进程ID号
    BOOL bInProcList;     //当前的进程中是否有这个
}MON_STRUCT;
typedef CArray<MON_STRUCT,MON_STRUCT> CMoniData;
class CProcessManger
{
public:
    void SaveData();
    void LoadData();
    CMoniData m_listMonitor;         //要监视的文件名列表
    BOOL AddMonData(LPCTSTR sExeFile,int type=1);
    char m_Err[1024];
    BOOL CheckMonitor();
    CProcessManger();
    virtual ~CProcessManger();

private:
    CString m_confile;
    UINT IsFileInList(LPCTSTR file);
    int GetMonIndex(LPCTSTR sExeFile);
    void TerminateProcessID(DWORD id);
    CString GetProcessPath(DWORD idProcess);
    CString GetProcessBaseModuleName(DWORD idProcess);
    void CheckExeApp();
    int m_nProcessCount;
    unsigned long m_iKernelTime;
    DWORD m_aProcesses[1024];
    DWORD GetProcessIDs(DWORD *pdwBuffer, DWORD dwSizeBuffer);
    int FindIsResponding(MON_STRUCT &mon);
};
extern CProcessManger g_pm;
#endif // !defined(AFX_PROCESSMANGER_H__E49C1DBD_4E0B_4456_8CF1_5C6A712CB3E9__INCLUDED_)
hjl0508 2014-05-09
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
“心跳防护”这个思路本身就错了。 为什么要搞心跳防护?因为被检测进程不时心脏停跳。 为什么被检测进程不时心脏停跳?因为被检测进程亚健康。 怎么知道被检测进程亚健康的原因: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏! 根治了被检测进程亚健康→被检测进程不再心脏停跳→不用再搞心跳防护。 越依赖心跳防护→被检测进程心脏停跳越频繁→被检测进程越不健康! 怎么心跳防护“用来心跳防护不健康进程C”的进程B的不健康? 怎么心跳防护“用来心跳防护‘用来心跳防护不健康进程C”的进程B’的进程A”的不健康?
额。。。。赵老师,现在不是写这个对不对的问题,而是上边给我的任务,必须得写,现在的问题是该怎么写。。。。
赵4老师 2014-05-09
  • 打赏
  • 举报
回复
“心跳防护”这个思路本身就错了。 为什么要搞心跳防护?因为被检测进程不时心脏停跳。 为什么被检测进程不时心脏停跳?因为被检测进程亚健康。 怎么知道被检测进程亚健康的原因: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏! 根治了被检测进程亚健康→被检测进程不再心脏停跳→不用再搞心跳防护。 越依赖心跳防护→被检测进程心脏停跳越频繁→被检测进程越不健康! 怎么心跳防护“用来心跳防护不健康进程C”的进程B的不健康? 怎么心跳防护“用来心跳防护‘用来心跳防护不健康进程C”的进程B’的进程A”的不健康?

65,208

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧