//softwareWdt.h
/*
*功能: 监测各线程间的运行状态(软看门狗)
*
*作者:JDSH
*
*时间:2015-01-15 22:20
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "Typedef.h"


#define REQUEST_WDT_MAX_NUM 20

class CSoftwareWdt
{
private:
bool m_fReqWdtFlg[REQUEST_WDT_MAX_NUM]; //=true 已经申请ID成功,=false反之

WORD m_wWdtTimeout[REQUEST_WDT_MAX_NUM];

WORD m_wWdtCount[REQUEST_WDT_MAX_NUM];

public:
CSoftwareWdt();

~CSoftwareWdt();

int RequestSoftwareWdtID(const char *cThreadName, WORD wTimeout);

bool ReleaseSoftwareWdtID(const char *cThreadName, WORD wTimeout);

bool KeepSoftwareWdtAlive(WORD wWdtId);

void MontiorWdtRunState();
};


#include "SoftwareWdt.h"

CSoftwareWdt::CSoftwareWdt()
{
BYTE bId;

for (bId = 0; bId < REQUEST_WDT_MAX_NUM; bId++)
m_fReqWdtFlg[bId] = false;
memset(m_wWdtTimeout, 0x00, sizeof(m_wWdtTimeout));
memset(m_wWdtCount, 0x00, sizeof(m_wWdtCount));
}

CSoftwareWdt::~CSoftwareWdt()
{
;
}

/*
* 功能:申请软件狗的ID
* 返回:申请失败返回-1,成功返回申请到ID
*
*/
int CSoftwareWdt::RequestSoftwareWdtID(const char *cThreadName, WORD wTimeout)
{
BYTE bId;
int iRet = -1;

for (bId = 0; bId < REQUEST_WDT_MAX_NUM; bId++)
{
if (m_fReqWdtFlg[bId] == false) //等于0、表示该ID还没有被申请过,可以使用
{
m_wWdtTimeout[bId] = wTimeout;
m_wWdtCount[bId] = 0;
m_fReqWdtFlg[bId] = true;
printf("The thread %s request ID=%d successful. Timeout=%d\n",
cThreadName, bId, wTimeout);
return bId;
}
}

return iRet;
}

bool CSoftwareWdt::ReleaseSoftwareWdtID(const char *cThreadName, WORD wWdtId)
{
bool fRet = false;

if (wWdtId > REQUEST_WDT_MAX_NUM)
{
printf("The thread %s ID=%d is over MAX ID=%d\n",
cThreadName, wWdtId, REQUEST_WDT_MAX_NUM);
return false;
}

if (m_fReqWdtFlg[wWdtId] != 0)
{
fRet = true;
m_fReqWdtFlg[wWdtId] = false;
m_wWdtTimeout[wWdtId] = 0;
m_wWdtCount[wWdtId] = 0;
printf("Release thread %s ID=%d\n", cThreadName, wWdtId);
}

return fRet;
}

bool CSoftwareWdt::KeepSoftwareWdtAlive(WORD wWdtId)
{
if (wWdtId > REQUEST_WDT_MAX_NUM)
return -1;

printf("Keep software Wdt Id=%d\n", wWdtId);
m_wWdtCount[wWdtId] =0;

return true;
}

void CSoftwareWdt::MontiorWdtRunState()
{
BYTE bId;

for (bId = 0; bId < REQUEST_WDT_MAX_NUM; bId++)
{
if (m_fReqWdtFlg[bId])
{
if (m_wWdtCount[bId]++ > m_wWdtTimeout[bId])
{
printf("The Wdt ID=%d is timeout\n", bId);
system("reboot");
}
}
}
}

CSoftwareWdt *g_CsoftwareWdt;

int main(int argc, char *argv[])
{
const char *sThreadName[10] = {"One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten"};
WORD wTimeout = 30;
BYTE bId =0;

printf("\n\n\n");
printf("*********************************************\n");
printf("**************Software wdt Test**************\n");
printf("*********************************************\n");
printf("\n");

g_CsoftwareWdt = new CSoftwareWdt();

for (bId = 0; bId < 10; bId++)
{
g_CsoftwareWdt->RequestSoftwareWdtID(sThreadName[bId], wTimeout);
}

bId = 0;
while (1)
{
g_CsoftwareWdt->MontiorWdtRunState();
sleep(1);
g_CsoftwareWdt->KeepSoftwareWdtAlive(bId);
bId++;
if (bId > 10)
bId = 0;
}

delete g_CsoftwareWdt;
}

说明:本部分的功能是实现一个软看门狗,用于监测各个线程的运行状态,使用时必须先申请看门狗线程的ID,为了合理的运用软看门狗的资源,线程退出时必须释放看门狗,某个线程超时,将通过调试信息打印超时线程,并最终唤起系统重启,注意这个软看门狗与硬件看门狗的区别。此程序原创,转载请指明出处,如存在缺陷,欢迎指正!