linux fcntl + F_NOTIFY没有按预期工作:当有更改时,没有触发任何内容

时间:2016-12-27 05:24:01

标签: file directory monitor inotify fcntl

我在RHEL5上使用内核2.6.32。试图查看fcntl + F_NOTIFY是否可以监视目录或文件更改。我搜索了谷歌并找到了这个文件:

#define _GNU_SOURCE

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

static volatile int event_fd;

static void handler(int signum, siginfo_t *si, void *data){
    event_fd = si->si_fd;
    printf("info size:%d, data:%d/n", sizeof(siginfo_t), sizeof(data));
}

int main(int argc, char **argv){
    struct sigaction action;
    int fd;
    action.sa_sigaction = handler;
    sigemptyset(&action.sa_mask);
    action.sa_flags = SA_SIGINFO;
    sigaction(SIGRTMIN+1, &action, NULL);

    fd = open("test", O_RDONLY);
    fcntl(fd, F_SETSIG, SIGRTMIN+1);
    fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);

    fd = open(".", O_RDONLY);
    fcntl(fd, F_SETSIG, SIGRTMIN+1);
    fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);
    while(1){
        pause();
        printf("got event on fd=%d/n", event_fd);
    }
}

我将它编译为./a.out。

在另一个终端,我创建了一个名为&#34; test.txt&#34;的空文件。然后我开始./a.out。现在我要改变&#34; test.txt&#34;或触摸/删除&#34;。&#34;下的文件。 ./a.out

没有输出

我理解有什么不对吗?我希望当我改变&#34; test.txt&#34;或者更改当前目录的任何操作,它应该触发我的&#34;处理程序&#34;功能和打印出来的东西。

有任何解释吗?

感谢Andrew的解释,是的,这是一个错误的输入和asyn问题,修正如下:

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
static volatile int event_fd;
static void handler(int signum, siginfo_t *si, void *data){
    event_fd = si->si_fd;
    char msg[100];
    sprintf(msg, "info size:%d, data:%d\n", sizeof(siginfo_t), sizeof(data));
    write(STDOUT_FILENO, msg, strlen(msg));
}
int main(int argc, char **argv){
    struct sigaction action;
    int fd;
    action.sa_sigaction = handler;
    sigemptyset(&action.sa_mask);
    action.sa_flags = SA_SIGINFO;
    sigaction(SIGRTMIN+1, &action, NULL);

    fd = open("./test.txt", O_RDONLY);
    fcntl(fd, F_SETSIG, SIGRTMIN+1);
    fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);

    fd = open(".", O_RDONLY);
    fcntl(fd, F_SETSIG, SIGRTMIN+1);
    fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);
    while(1){
        pause();
        char msg[100];
        sprintf(msg, "got event on fd=%d\n", event_fd);
        write(STDOUT_FILENO, msg, strlen(msg));
    }
}

所以它有效。非常感谢。

1 个答案:

答案 0 :(得分:1)

首先,在信号处理程序中调用printf()是不安全的。可以从信号处理程序中安全地调用 async-signal-safe函数。可以在http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04

找到POSIX指定的异步信号安全功能列表

请注意,printf()不是异步信号安全函数之一。

其次,您的printf()函数调用可能是行缓冲的,并且您不会使用换行符终止输出:

printf("info size:%d, data:%d/n", sizeof(siginfo_t), sizeof(data));

请注意,您使用"/n"结束字符串,这是一个正斜杠'/'后跟字符'n',而不是换行符,这将是反斜杠'\'然后是'n'"\n"。假设您的stdout流是Linux默认的行缓冲,在输出缓冲区已满之前不会发出任何输出,可能是4或8 kB。如果它完全有效并且没有死锁,因为printf()是异步信号 - 不安全 功能。