使用inotify为什么我的监视文件被忽略了?

时间:2013-05-26 14:48:08

标签: d inotify

我正在Linux上使用D子系统在inotify编写一个文件监视器来进行事件通知。我已经在下面编写了一些代码,我差点就在那里,但我有一个问题,即被监视的文件被切换为忽略,并且不再为它提出任何事件。

看起来这个人有类似的问题,但那里没有答案:Inotify vim modification

请考虑以下代码:

/**
 * Imports.
 */
import core.sys.posix.unistd;
import core.sys.posix.sys.select;
import inotify;
import std.stdio;

/**
 * Main.
 */
void main(string[] arguments)
{
    immutable int EVENT_BUF_LEN = (1024 * (inotify_event.sizeof + 16));

    auto inotifyInstance = inotify_init();

    if (inotifyInstance >= 0)
    {
        string watchedFile = "/home/gary/Desktop/test.txt";
        char[EVENT_BUF_LEN] buffer;
        void* pointer;

        auto watchDescriptor = inotify_add_watch(inotifyInstance, cast(char*)watchedFile, IN_ALL_EVENTS);

        while (true)
        {
            fd_set rfds;
            FD_ZERO(&rfds);
            FD_SET(inotifyInstance, &rfds);

            timeval timeout;
            timeout.tv_sec  = 5;
            timeout.tv_usec = 0;

            if (select(FD_SETSIZE, &rfds, null, null, &timeout))
            {
                auto inotifyResult = read(inotifyInstance, buffer.ptr, buffer.length);

                for (pointer = buffer.ptr; pointer < buffer.ptr + inotifyResult; )
                {
                    inotify_event* event = cast(inotify_event*)pointer;

                    if (event.mask & IN_ACCESS)
                    {
                        writeln("IN_ACCESS");
                    }

                    if (event.mask & IN_MODIFY)
                    {
                        writeln("IN_MODIFY");
                    }

                    if (event.mask & IN_ATTRIB)
                    {
                        writeln("IN_ATTRIB");
                    }

                    if (event.mask & IN_CLOSE_WRITE)
                    {
                        writeln("IN_CLOSE_WRITE");
                    }

                    if (event.mask & IN_CLOSE_NOWRITE)
                    {
                        writeln("IN_CLOSE_NOWRITE");
                    }

                    if (event.mask & IN_OPEN)
                    {
                        writeln("IN_OPEN");
                    }

                    if (event.mask & IN_MOVED_FROM)
                    {
                        writeln("IN_MOVED_FROM");
                    }

                    if (event.mask & IN_MOVED_TO)
                    {
                        writeln("IN_MOVED_TO");
                    }

                    if (event.mask & IN_CREATE)
                    {
                        writeln("IN_CREATE");
                    }

                    if (event.mask & IN_DELETE)
                    {
                        writeln("IN_DELETE");
                    }

                    if (event.mask & IN_DELETE_SELF)
                    {
                        writeln("IN_DELETE_SELF");
                    }

                    if (event.mask & IN_MOVE_SELF)
                    {
                        writeln("IN_MOVE_SELF");
                    }

                    if (event.mask & IN_UMOUNT)
                    {
                        writeln("IN_UMOUNT");
                    }

                    if (event.mask & IN_Q_OVERFLOW)
                    {
                        writeln("IN_Q_OVERFLOW");
                    }

                    if (event.mask & IN_IGNORED)
                    {
                        writeln("IN_IGNORED");
                    }

                    if (event.mask & IN_CLOSE)
                    {
                        writeln("IN_CLOSE");
                    }

                    if (event.mask & IN_MOVE)
                    {
                        writeln("IN_MOVE");
                    }

                    if (event.mask & IN_ONLYDIR)
                    {
                        writeln("IN_ONLYDIR");
                    }

                    if (event.mask & IN_DONT_FOLLOW)
                    {
                        writeln("IN_DONT_FOLLOW");
                    }

                    if (event.mask & IN_EXCL_UNLINK)
                    {
                        writeln("IN_EXCL_UNLINK");
                    }

                    if (event.mask & IN_MASK_ADD)
                    {
                        writeln("IN_MASK_ADD");
                    }

                    writefln("wd: %s - mask: 0x%08x - cookie: %s - len: %s", event.wd, event.mask, event.cookie, event.len);

                    pointer += inotify_event.sizeof + event.len;
                }

            }
        }

        inotify_rm_watch(inotifyInstance, watchDescriptor);
        close(inotifyInstance);
    }
}

如果我执行以下操作,我会得到以下结果:

  1. 触摸〜/ Desktop / test.txt

      

    IN_OPEN
      wd:1 - mask:0x00000020 - cookie:0 - len:0
      IN_IGNORED
      wd:1 - mask:0x00008000 - cookie:0 - len:0

  2. 回声“玛丽有一只小羊羔。” &GT;&GT; 〜/桌面/ test.txt的

      

    IN_OPEN
      wd:1 - mask:0x00000020 - cookie:0 - len:0
      IN_IGNORED
      wd:1 - mask:0x00008000 - cookie:0 - len:0

  3. 在Vim中打开,修改和:wq

      

    IN_OPEN
      wd:1 - mask:0x00000020 - cookie:0 - len:0
      IN_IGNORED
      wd:1 - mask:0x00008000 - cookie:0 - len:0

  4. 此处似乎没有任何作用,触发打开事件后文件将被忽略。

    如果我改变代码并更改IN_ALL_EVENTS标志(检查所有事件)并改为使用IN_MODIFY,我会得到以下内容:

    1. 触摸〜/ Desktop / test.txt

        

      没有结果。

    2. 回声“玛丽有一只小羊羔。” &GT;&GT; 〜/桌面/ test.txt的

        

      IN_MODIFY   wd:1 - mask:0x00000002 - cookie:0 - len:0

    3. 在Vim中打开,修改和:wq

        

      IN_IGNORED   wd:1 - mask:0x00008000 - cookie:0 - len:0

    4. 只有第2点似乎正常工作。

      任何想法我在这里做错了什么以及有关更改代码以正确获取文件的所有修改事件的任何想法?

1 个答案:

答案 0 :(得分:6)

经过一番阅读后,我对代码进行了一些修改,似乎已经解决了问题。附加到该文件会引发一个IN_MODIFY事件,该事件很好地被捕获。 Touch会引发IN_ATTRIB我们可以视为修改。 Vim(和其他编辑)在提出最终IN_ATTRIB之前提出IN_DELETE_SELFIN_MOVE_SELFIN_IGNORED事件,所以我现在可以处理这些事件。如果我遇到IN_IGNORED事件,我会重新初始化inotify。

/**
 * Imports.
 */
import core.sys.posix.unistd;
import core.sys.posix.sys.select;
import inotify;
import std.stdio;

/**
 * Main.
 */
void main(string[] arguments)
{
    immutable int  EVENT_BUFFER_LENGTH = (inotify_event.sizeof + 16) * 1024;
    immutable uint NOTIFICATION_FLAGS  = IN_MODIFY | IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_IGNORED;

    auto inotifyInstance = inotify_init();

    if (inotifyInstance >= 0)
    {
        string watchedFile = "/home/gary/Desktop/test.txt";
        char[EVENT_BUFFER_LENGTH] eventBuffer;
        void* eventPointer;

        auto watchDescriptor = inotify_add_watch(inotifyInstance, cast(char*)watchedFile, NOTIFICATION_FLAGS);

        while (true)
        {
            fd_set fileDescriptorSet;

            FD_ZERO(&fileDescriptorSet);
            FD_SET(inotifyInstance, &fileDescriptorSet);

            timeval timeout;
            timeout.tv_sec  = 5;
            timeout.tv_usec = 0;

            if (select(FD_SETSIZE, &fileDescriptorSet, null, null, &timeout))
            {
                auto bytesRead = read(inotifyInstance, eventBuffer.ptr, eventBuffer.length);

                for (eventPointer = eventBuffer.ptr; eventPointer < eventBuffer.ptr + bytesRead; null)
                {
                    inotify_event* event = cast(inotify_event*)eventPointer;

                    if (event.mask & IN_MODIFY || event.mask & IN_ATTRIB)
                    {
                        writeln("Modified");
                    }

                    if (event.mask & IN_DELETE_SELF || event.mask & IN_MOVE_SELF || event.mask & IN_IGNORED)
                    {
                        writeln("Modified");
                        inotify_rm_watch(inotifyInstance, watchDescriptor);
                        close(inotifyInstance);
                        inotifyInstance = inotify_init();
                        watchDescriptor = inotify_add_watch(inotifyInstance, cast(char*)watchedFile, NOTIFICATION_FLAGS);
                    }

                    eventPointer += inotify_event.sizeof + event.len;
                }
            }
        }

        inotify_rm_watch(inotifyInstance, watchDescriptor);
        close(inotifyInstance);
    }
}