【问题标题】:Asynchronous reading on the inotify descriptor failed异步读取 inotify 描述符失败
【发布时间】:2013-05-06 10:06:46
【问题描述】:

我正在写一个基于源码的监控文件程序: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,OPEN ...),以进行受监视文件的第一次更改。之后再次调用 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

}

你们能帮我解释一下吗????我很想得到你的答案.....

【问题讨论】:

  • 你能把boost::asioinotify结合起来吗?

标签: asynchronous boost-asio inotify file-monitoring


【解决方案1】:

我觉得这很可疑

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_)));
}

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

【讨论】:

  • 感谢您的回答,我重写了 fd 变量。但这不是问题。我缩小了这个问题的问题范围。 stackoverflow.com/questions/16397293/…你能帮我解释一下吗。希望看到你的回答
【解决方案2】:

我会说,而不是使用

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));

【讨论】:

    【解决方案3】:
    #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;
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2017-01-19
    相关资源
    最近更新 更多