linux 文件监控,linux下c++实现文件监控

#ifndef _HOTSWITCH_DICT_H_

#define _HOTSWITCH_DICT_H_

#include

#include

#include

#include

#include

#include

#include

#include

using std::string;

using std::cerr;

using std::endl;

using std::cout;

namespace hsd {

/** *@brief 获取当前时间 */

inline string _getCurrentTime()

{

time_t t = time(NULL);

/*本地时间:日期,时间 年月日,星期,时分秒*/

struct tm* c_t = localtime(&t);

char buf[20];

sprintf(buf, "%d-%d-%d %d:%d:%d", c_t->tm_year+1900, c_t->tm_mon,

c_t->tm_mday, c_t->tm_hour, c_t->tm_min, c_t->tm_sec);

return string(buf);

}

template class HotSwitchDict;

template

void* monitorThread(void *arg)

{

HotSwitchDict * pHotDict = (HotSwitchDict*)arg;

bool needSleep = false;

uint32_t curSleepTime = 0;

// 检测是否需要停止检测

while( !pHotDict->m_stopMonitor )

{

if( needSleep ) {

if( curSleepTime++ < pHotDict->m_sleepTime ) {

sleep(1);

continue;

}

else {

needSleep = false;

curSleepTime = 0;

}

}

// 检测pHotDict->m_pSwitchDict是否不为空 2012-08-12

// 不为空,判断是否到底备用词典的延迟生命周期

if( pHotDict->m_pSwitchDict != NULL ) {

delete pHotDict->m_pSwitchDict;

pHotDict->m_pSwitchDict = NULL;

}

// 检测新文件是否到来

if(pHotDict->isNewDictArrived())

{

// 构造新的DictType类型指针

pHotDict->m_pSwitchDict =

pHotDict->newDictFunc(pHotDict->getNewDictFileName());

// 判断词典是否加载成功

if(pHotDict->m_pSwitchDict == NULL) {

cerr << "[WARNING] [" << _getCurrentTime() <<

"] Error when load new Dictionary!" << endl;

}

else {

// 加读锁后,交换m_pCurDict和m_pSwitchDict指针

DictType * pDictTemp = pHotDict->m_pCurDict;

pthread_rwlock_wrlock(&pHotDict->m_rwLock);

pHotDict->m_pCurDict = pHotDict->m_pSwitchDict;

// 不在删除,直接将m_pSwitchDict指向原来的内存空间

// 保证指针不删除原来m_pCurDict的指针

pHotDict->m_pSwitchDict = pDictTemp;

pthread_rwlock_unlock(&pHotDict->m_rwLock);

// delete pDictTemp;

// 修改当前内存中的词典名字

pHotDict->switchFileName();

cout << "[INFO] [" << _getCurrentTime()

<< "] New Dictionary Switched!" << endl;

}

needSleep = true;

}

else { // 继续监控

needSleep = true;

}

}

return NULL;

}

// 默认的词典构建对象函数

template

inline DictType * DefaultNewDictFunc(const string & fileName)

{

DictType * tmpDict;

try {

tmpDict = new DictType(fileName.c_str());

}

catch (int e) {

return NULL;

}

return tmpDict;

}

template

class HotSwitchDict

{

public:

typedef DictType* (*NewDictFunc)(const string & fileName);

// 友元函数,需要操作HotSwitchDict的private变量

friend void * monitorThread(void * arg);

/** *@brief HotSwitchDict 构造函数 *@param fileName 词典的文件名 *@param flagFile 词典的监控文件,保存新词典的名字和md5码 *@param sleepTime 每次词典监控的扫描时间间隔 */

HotSwitchDict(const string & fileName, const string & flagFile,

uint32_t sleepTime = 1)

: m_pCurDict(NULL), m_pSwitchDict(NULL), m_fileName(fileName),

m_newFileName(""), m_flagFile(flagFile), m_sleepTime(sleepTime),

m_stopMonitor(false)

{

pthread_rwlock_init(&m_rwLock, NULL);

m_lastUpdateTime = 0;

if( sleepTime < 10 || sleepTime > 3600 ) {

m_sleepTime = 3600;

}

}

/** *@brief 初始化函数,用来初始化词典文件以及监控线程 *@ndf 初始化词典的函数指针 *@return 如果初始化不成功,返回false */

bool init(NewDictFunc ndf)

{

this->setNewDictFunc(ndf);

m_pCurDict = newDictFunc(m_fileName);

if( m_pCurDict == NULL ) {

return false;

}

int err = pthread_create(&m_monitorThread, NULL,

monitorThread, (void*)this);

if( err != 0 ) return false;

return true;

}

/** *@brief 销毁对象,等待监控xiancheng结束,销毁dict指针和读写锁 * todo 屏蔽继承 */

~HotSwitchDict()

{

if( m_pCurDict != NULL )

{

m_stopMonitor = true;

// 取消线程,避免出现sleep时间过长,导致join需要大量时间

//pthread_cancel(m_monitorThread);

// 等待监控线程结束

pthread_join(m_monitorThread, NULL);

// 销毁对象

delete m_pCurDict;

}

m_pCurDict = NULL;

if( m_pSwitchDict != NULL ) {

delete m_pSwitchDict;

m_pSwitchDict = NULL;

}

// 销毁锁

pthread_rwlock_destroy(&m_rwLock);

}

/** *@brief 获取当前dict的指针 */

DictType * getCurDict()

{

return m_pCurDict;

}

/** *@brief 加读锁 */

int32_t rwlock_read_lock()

{

return pthread_rwlock_rdlock(&m_rwLock);

}

/** *@brief 加写锁 */

int32_t rwlock_write_lock()

{

return pthread_rwlock_wrlock(&m_rwLock);

}

/** *@brief 解开锁 */

int32_t rwlock_unlock()

{

return pthread_rwlock_unlock(&m_rwLock);

}

private:

HotSwitchDict() {}

/** *@brief 根据词典文件创建新的dict指针 */

DictType * newDictFunc(const string & fileName)

{

return m_newDictFunc(fileName.c_str());

}

/** *@brief 判断新词典文件是否存在 */

bool isNewDictArrived()

{

// 读取finish文件,得到新词典对应的文件名

if( access(m_flagFile.c_str(), F_OK|R_OK) < 0 )

{

cerr << "[WARNING] [" << _getCurrentTime() << "] flagFile "

<< m_flagFile << " not exist or not readable" << endl;

return false;

}

// 如果文件修改时间比m_lastUpdateTime大,则读取文件

struct stat buf;

if( stat(m_flagFile.c_str(), &buf) < 0 ) {

return false;

}

time_t flagFileTime = buf.st_ctime;

if( flagFileTime <= m_lastUpdateTime )

{

#ifdef DEBUG

cout << "[DEBUG] flagFileTime is smaller than m_lastUpdateTime" << endl;

#endif

return false;

}

std::ifstream in(m_flagFile.c_str());

if( !in.is_open() ) {

cerr << "[ERROR] [" << _getCurrentTime() << "] flagFile "

<< m_flagFile << " opened failed" << endl;

return false;

}

string newfileName;

in >> newfileName;

in.close();

// 判定新文件名是否发生变化

if( newfileName == m_fileName ) {

#ifdef DEBUG

cout << "[DEBUG] newfileName == m_fileName" << endl;

#endif

return false;

}

// 判断新文件是否存在,使用绝对路径

if( access(newfileName.c_str(), F_OK|R_OK) < 0 )

{

cerr << "[WARN] [" << _getCurrentTime() << "] newfileName "

<< newfileName << " not exist or not readable" << endl;

return false;

}

// 保存md5码,并进行验证

m_newFileName = newfileName;

m_lastUpdateTime = flagFileTime;

#ifdef DEBUG

cout << "[DEBUG] [" << _getCurrentTime() <<

"] change m_newFileName to " << m_newFileName << endl;

#endif

return true;

}

string getNewDictFileName()

{

return m_newFileName;

}

/** *@brief 当前词典的文件名修改 */

void switchFileName()

{

m_fileName = m_newFileName;

m_newFileName = "";

}

/** *@brief 设置从一个文件初始化DictType*类型的函数 */

void setNewDictFunc(NewDictFunc ndf)

{

m_newDictFunc = ndf;

}

private:

DictType * m_pCurDict;

DictType * m_pSwitchDict;

string m_fileName;

string m_newFileName;

string m_flagFile;

uint32_t m_sleepTime;

pthread_rwlock_t m_rwLock;

pthread_t m_monitorThread;

bool m_stopMonitor;

NewDictFunc m_newDictFunc;

time_t m_lastUpdateTime;

};

}

#endif // _HOTSWITCH_DICT_H_

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux C/C中,可以使用inotify API来监控文件系统的事件。inotify API提供了一种异步的、高效的文件系统事件监控机制,可以监控文件或目录的创建、删除、修改、移动等操作。 使用inotify API需要先创建一个inotify实例,并使用inotify_add_watch函数添加要监控文件或目录。当文件系统中发生对应的事件时,inotify会通知应用程序。 下面是一个简单的例子,演示如何使用inotify API监控文件变化: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/inotify.h> #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) int main( int argc, char **argv ) { int length, i = 0; int fd; int wd; char buffer[BUF_LEN]; fd = inotify_init(); if ( fd < 0 ) { perror( "inotify_init" ); } wd = inotify_add_watch( fd, "/tmp", IN_MODIFY | IN_CREATE | IN_DELETE ); while ( 1 ) { i = 0; length = read( fd, buffer, BUF_LEN ); if ( length < 0 ) { perror( "read" ); } while ( i < length ) { struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ]; if ( event->len ) { if ( event->mask & IN_CREATE ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was created.\n", event->name ); } else { printf( "The file %s was created.\n", event->name ); } } else if ( event->mask & IN_DELETE ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was deleted.\n", event->name ); } else { printf( "The file %s was deleted.\n", event->name ); } } else if ( event->mask & IN_MODIFY ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was modified.\n", event->name ); } else { printf( "The file %s was modified.\n", event->name ); } } } i += EVENT_SIZE + event->len; } } ( void ) inotify_rm_watch( fd, wd ); ( void ) close( fd ); exit( 0 ); } ``` 上面的代码中,先使用inotify_init函数创建一个inotify实例,然后使用inotify_add_watch函数添加要监控的目录。在while循环中,使用read函数读取inotify实例中的事件,然后根据事件类型进行相应的处理。最后使用inotify_rm_watch函数移除监控项,关闭inotify实例。 需要注意的是,inotify API只能用于Linux系统,其他操作系统需要使用不同的机制来监控文件系统事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值