在vxWorks下,经常会遇到突然掉电后,文件系统被破坏,文件不能使用的情况。前几天我做了一个reboot的hook,使用rebootHookAdd增加到reboot函数中后,可以在系统复位前中止正在做写操作的任务,然后关闭文件和文件系统,同步cache,做到安全掉电。代码如下:
#include "vxWorks.h"
#include "private/dosFsVerP.h"
#include "private/dosFsLibP.h"
#include "private/iosLibP.h"
#include "taskLib.h"
#include "intLib.h"
#define DOSFS_REBOOT_HOOK_DEBUG 1
#if DOSFS_REBOOT_HOOK_DEBUG
char *g_pszDbgDosfsHookBuf = 0x6000;
#endif
extern int dosFsDrvNum;
extern int maxDrivers;
extern int maxFiles;
extern DRV_ENTRY *drvTable;
void usrDosfsShutdown()
{
int iLoop, fdNum, iCount = 0, iStatus = 0;
DEV_HDR *pDev = NULL;
DOS_VOLUME_DESC_ID pVolDesc;
DOS_FILE_DESC_ID pFd = pVolDesc->pFdList;
#if DOSFS_REBOOT_HOOK_DEBUG
int iCloseFlag = 0;
char szTmpBuf[1024];
int curTick = tickGet();
*(unsigned long *)g_pszDbgDosfsHookBuf = 0;
#endif
if ((drvTable != NULL)
&&(dosFsDrvNum != ERROR)&&(dosFsDrvNum < maxDrivers)
&&(drvTable[dosFsDrvNum].de_inuse == TRUE))
{
for (iLoop = 0; iLoop < maxDrivers; iLoop++)
{
pDev = iosNextDevGet(pDev);
if (pDev == NULL)
{
break;
}
/* All used dosfs function group is dosfs vol */
if (pDev->drvNum == dosFsDrvNum)
{
pVolDesc = (DOS_VOLUME_DESC_ID)pDev;
#if DOSFS_REBOOT_HOOK_DEBUG
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
"Start check volume %s, can open max %d files, have used %d fds.\r\n",
pDev->name, pVolDesc->maxFiles, pVolDesc->nBusyFd);
#endif
iCount = 0;
for (pFd = pVolDesc->pFdList;
pFd < pVolDesc->pFdList + pVolDesc->maxFiles; pFd++)
{
if (pFd->busy == TRUE)
{
#if DOSFS_REBOOT_HOOK_DEBUG
iCloseFlag = 0;
#endif
/* Force dosfs make a mistake, the operating will exit. */
pFd->fatHdl.errCode = TRUE;
for (fdNum = 0; fdNum < maxFiles; fdNum++)
{
if ((DOS_FILE_DESC_ID)iosFdValue(fdNum) == pFd)
{
#if DOSFS_REBOOT_HOOK_DEBUG
strcpy(szTmpBuf, fdTable[STD_MAP(fdNum)].name);
#endif
if (close(fdNum) == OK)
{
#if DOSFS_REBOOT_HOOK_DEBUG
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
" Closed %s success(fd==%d).\r\n",
szTmpBuf, fdNum);
#endif
iCount++;
iCloseFlag = TRUE;
}
else
{
#if DOSFS_REBOOT_HOOK_DEBUG
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
" Close %s failed(fd==%d).\r\n",
szTmpBuf, fdNum);
#endif
}
}
}
#if DOSFS_REBOOT_HOOK_DEBUG
if (iCloseFlag == 0)
{
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
" Find a file openned, but can't find its fd.");
}
#endif
}
}
iStatus = dosFsVolUnmount(pVolDesc);
#if DOSFS_REBOOT_HOOK_DEBUG
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
"Check volume %s over, closed %d files, unmount volume %s.\r\n",
pDev->name,iCount,((iStatus==OK)?"success":"failed"));
#endif
}
}
}
else
{
#if DOSFS_REBOOT_HOOK_DEBUG
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
"Can't find dosfs volume!\r\n");
#endif
}
#if DOSFS_REBOOT_HOOK_DEBUG
sprintf(g_pszDbgDosfsHookBuf + strlen(g_pszDbgDosfsHookBuf),
"Check all dosfs volume, cost %d ticks.!\r\n", tickGet() - curTick);
#endif
}