2013-05-06 149 views
2

我基于源代码的编写监控文件的程序:https://github.com/kvikas/file-monitor-service/blob/master/异步读取失败

我的程序使用的boost ::支持ASIO :: stream_descriptor :: async_read_some()从异步读取inotify的描述http://linux.die.net/man/7/inotify

我的代码如下:

构造:

void init(){ 
    int fd = inotify_init1(IN_NONBLOCK); 
    int wd = inotify_add_watch(fd_, "./test.txt", IN_ALL_EVENTS); 
    stream_.reset(new boost::asio::posix::stream_descriptor(io_service_, fd_))); 
} 

的异步读取:

template<typename Monitor_Handler> 
void async_monitor(Monitor_Handler handler) { 
    stream_->async_read_some(boost::asio::buffer(buffer_), 
      boost::bind(&monitor::handle_monitor<Monitor_Handler>, 
        shared_from_this(), boost::asio::placeholders::error, 
        boost::asio::placeholders::bytes_transferred, handler)); 
} 

的处理程序:

template<typename Monitor_Handler> 
void handle_monitor(const boost::system::error_code &ec, 
     std::size_t bytes_transferred, Monitor_Handler handler) {  
    //process buffer  
    async_monitor(handler); 

} 

的错误是,在第一handle_monitor是在第一个变化调用几次(多个事件如MODIFY,Access中打开...)受监控的文件。之后async_read_some方法被再次调用,但我没有信号了(该handle_monitor不再被调用)

然而,当我试图重启inotify的描述,并再次重新进行添加的监视的文件==>它的工作中, handle_monitor被调用来监视这些文件中的新变化。

修改代码:

template<typename Monitor_Handler> 
void handle_monitor(const boost::system::error_code &ec, 
     std::size_t bytes_transferred, Monitor_Handler handler) {  
    //process buffer  
    async_monitor(handler); 
    init();//for resetting the inotify desciptor 

} 

难道你们帮我解释一下这个????我渴望你的答案.....

回答

2

这看起来可疑我

void init(){ 
    int fd = inotify_init1(IN_NONBLOCK); 
    int wd = inotify_add_watch(fd_, "./test.txt", IN_ALL_EVENTS); 
    stream_.reset(new boost::asio::posix::stream_descriptor(io_service_, fd_))); 
} 

您应该创建stream_descriptornotify_init1()返回的值,这将是fd而不是fd_。我假设fd_是一个类成员,可能未初始化或初始化为0

+0

谢谢您的回答,我重写FD变量。但这不是问题。我在这个问题上缩小了我的问题的范围。 http://stackoverflow.com/questions/16397293/the-read-method-on-the-inotify-descriptor-does-not-return你能帮我解释一下吗?希望看到你的回答 – khanhhh89 2013-05-07 02:43:40

-1
#include <string> 
#include <algorithm> 
#include <cstring> 
#include <assert.h> 
#include <sys/signalfd.h> 
#include <sys/inotify.h> 

#include <boost/asio.hpp> 
#include <boost/array.hpp> 
#include <boost/bind.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/enable_shared_from_this.hpp> 
#include <iostream> 



//compile with 
//------------- 
//g++ -std=c++0x -g -I/usr/local/include -I/home/rk/Downloads/websocketpp/src asio.cc -L/home/rk/Downloads/websocketpp -L/usr/local/lib/ -lwebsocketpp -lboost_thread -lboost_exception -lboost_date_time -lboost_regex -lboost_system -o asio 

static int inotifyFd = -1; 
static int signalFd = -1; 
static boost::asio::io_service gIoSvc; 
//A simple test program to test whether signalfd works with boost::asio or not. 
static boost::asio::posix::stream_descriptor *gwMqFd = nullptr; //message queue on which the gateway listens for control requests. 
static boost::asio::posix::stream_descriptor *inFd = nullptr; //message queue on which the gateway listens for control requests. 
static void 
handleMqRead(boost::system::error_code ec) 
{ 
    std::cerr<<"\nRecvd signal"; 
    struct signalfd_siginfo fdsi; 
    memset(&fdsi, 0, sizeof(fdsi)); 
    ssize_t s = ::read(signalFd, &fdsi, sizeof(struct signalfd_siginfo)); 
    if (s != sizeof(struct signalfd_siginfo)){ 
     std::cerr<<"read() on signalfd returns inconsistent size."; 
     return; 
    } 
    gwMqFd->async_read_some(boost::asio::null_buffers(), 
      boost::bind(&handleMqRead, 
       boost::asio::placeholders::error)); 
    return; 
} 

#define EVENT_SIZE (sizeof (struct inotify_event)) 
#define EVENT_BUF_LEN (1024*(EVENT_SIZE + 16)) 
static void 
observeFilesystem(boost::system::error_code ec) 
{ 
    std::cerr<<"\nDirectory modified ..."; 
    char buf[EVENT_BUF_LEN]; 
    int length = ::read(inotifyFd, buf, sizeof(buf)); 
    inFd->async_read_some(boost::asio::null_buffers(), 
      boost::bind(&observeFilesystem, 
       boost::asio::placeholders::error)); 
    return; 
} 

int 
main(int argc, char* argv[]) 
{ 
    try{ 
     inFd = new boost::asio::posix::stream_descriptor(gIoSvc); 
     gwMqFd = new boost::asio::posix::stream_descriptor(gIoSvc); 
     sigset_t signalMask; 
     sigemptyset(&signalMask); 
     sigaddset(&signalMask, SIGCHLD); 
     sigaddset(&signalMask, SIGTERM); 
     sigprocmask(SIG_BLOCK, &signalMask, nullptr); 
     signalFd = signalfd(-1, &signalMask, SFD_NONBLOCK | SFD_CLOEXEC); 
     assert(signalFd > 0); 
     gwMqFd->assign(signalFd); 
     gwMqFd->async_read_some(boost::asio::null_buffers(), 
      boost::bind(&handleMqRead, 
       boost::asio::placeholders::error)); 

     inotifyFd = inotify_init(); 
     assert(inotifyFd > 0); 
     inFd->assign(inotifyFd); 
     std::string fqpn = "."; 
     inotify_add_watch(inotifyFd, fqpn.c_str(), IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY); 
     inFd->async_read_some(boost::asio::null_buffers(), 
      boost::bind(&observeFilesystem, 
       boost::asio::placeholders::error)); 
     gIoSvc.run(); 
    }catch (std::exception& e){ 
     std::cerr << "Exception: " << e.what() << std::endl; 
    } 
    return 0; 
} 
+0

-1。没有给出解释。它依赖于一个https://github.com/zaphoyd/websocketpp ..一个替代但更高级别的库。为+1添加一些解释:) – matiu 2017-06-21 18:37:01

1

我想说的,而不是使用

int length = ::read(inotifyFd, buf, sizeof(buf)); 
inFd->async_read_some(boost::asio::null_buffers(), 
boost::bind(&observeFilesystem, 
boost::asio::placeholders::error)) 

,倒不如完全利用aync_read_some如下

inFd->async_read_some(
boost::asio::buffer(buf, EVENT_BUF_LEN), 
boost::bind(&observeFilesystem, 
boost::asio::placeholders::error));