inotify example

本文介绍了一个使用inotify实现的文件及目录变更监控程序。通过监听指定路径下的创建、删除、修改等事件,程序能够实时反馈文件系统的变动情况,并对新增目录进行递归监控。
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
#include <errno.h>
#include <sys/inotify.h>

#include <time.h>
#include <fcntl.h>

static void
_inotify_event_handler(struct inotify_event *event ,int fd)
{

  const char* action = NULL;
  puts("***************handler event****************************/n");
  printf("event->mask: 0x%08x", event->mask);
  printf("/t/tevent->name: %s/n", event->name);

  if(event->mask & IN_ISDIR) 
    {
        if(event->mask & IN_DELETE)
        {
            printf("%s dir delete./n",event->name);
        }
        else if(event->mask & IN_CREATE)
        {
            printf("%s dir create./n",event->name);
            inotify_add_watch(fd, event->name, IN_ALL_EVENTS);
        }
        return ;
    }

  switch(event->mask)

    { 

        case IN_MODIFY:

        { 

            action = "IN_MODIFY";

            break;

        }

        case IN_CREATE:

        {

            action = "IN_CREATE";

            break;

        }

        case IN_DELETE:

        {

            action = "IN_DELETE";

            break;

        }

        case IN_MOVED_FROM:

        {

            action = "IN_MOVED_FROM";

            break;

        }

        case IN_MOVED_TO:

        {

            action = "IN_MOVED_TO";

            break;

        break;

        }

        default:break;

    }

    printf("/nevent->name=%s/t/taction=%s/n",event->name,action);
}

int
main(int argc, char **argv)
{
  if (argc != 2) {
    printf("Usage: %s <file/dir>/n", argv[0]);
    return -1;
  }

  int fd;
  int wd;
  struct timeval time;
  int ret;
  time.tv_sec = 10;
  time.tv_usec = 0;


  unsigned char buf[1024] = {0};
  struct inotify_event *event = {0};
   fd = inotify_init();
   wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS);

  for (;;) {
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    if ((ret=select(fd + 1, &fds, NULL, NULL, &time)) > 0) {
      int len, index = 0;
      while (((len = read(fd, &buf, sizeof(buf))) < 0) && (errno == EINTR));
      while (index < len) {
        event = (struct inotify_event *)(buf + index);
        _inotify_event_handler(event,fd);
        index += sizeof(struct inotify_event) + event->len;
      }
    }
 
    else if (!ret)
   { puts("time out/n");}

    else if(ret<0)
    {perror("select ");}
   
  }

  inotify_rm_watch(fd, wd);

  return 0;
}
<think> 我们提供一个使用inotify监控文件变化的C语言示例。该程序将监控指定文件(如`/tmp/test.txt`)的修改事件(IN_MODIFY),并在文件被修改时打印通知。 注意:实际使用时需要根据需求调整监控的文件路径和事件类型。 ```c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/inotify.h> #include <unistd.h> #include <limits.h> #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define BUF_LEN ( 1024 * ( EVENT_SIZE + NAME_MAX + 1 ) ) int main(int argc, char **argv) { int inotify_fd, watch_fd; char buffer[BUF_LEN]; // 检查参数 if (argc < 2) { fprintf(stderr, "Usage: %s <file-path>\n", argv[0]); exit(EXIT_FAILURE); } // 初始化inotify实例 inotify_fd = inotify_init(); if (inotify_fd == -1) { perror("inotify_init"); exit(EXIT_FAILURE); } // 添加监控,这里监控修改事件(IN_MODIFY) watch_fd = inotify_add_watch(inotify_fd, argv[1], IN_MODIFY); if (watch_fd == -1) { perror("inotify_add_watch"); close(inotify_fd); exit(EXIT_FAILURE); } printf("Monitoring file: %s (Press Ctrl+C to exit)\n", argv[1]); // 事件循环 while (1) { ssize_t len, i = 0; len = read(inotify_fd, buffer, BUF_LEN); if (len == -1 && errno != EAGAIN) { perror("read"); close(inotify_fd); exit(EXIT_FAILURE); } // 解析事件 while (i < len) { struct inotify_event *event = (struct inotify_event *) &buffer[i]; if (event->mask & IN_MODIFY) { printf("File %s was modified.\n", event->name); } i += EVENT_SIZE + event->len; } } // 清理(通常不会执行到这里,因为上面的循环是无限的) inotify_rm_watch(inotify_fd, watch_fd); close(inotify_fd); return EXIT_SUCCESS; } ``` ### 编译与运行示例: 1. **编译程序**: ```bash gcc inotify_example.c -o inotify_example ``` 2. **运行监控**(例如监控/tmp/test.txt): ```bash ./inotify_example /tmp/test.txt ``` 3. **测试修改**(另开终端): ```bash echo "test" >> /tmp/test.txt ``` ### 程序说明: - **监控目标**:通过命令行参数指定监控文件路径(如`/tmp/test.txt`) - **监控事件**:`IN_MODIFY`(文件内容修改) - **事件处理**:检测到修改时打印通知 - **运行要求**:需要读取目标文件的权限 ### 扩展建议: 1. 添加更多事件类型(如`IN_ACCESS`、`IN_ATTRIB`) 2. 实现递归目录监控 3. 结合epoll处理多个inotify实例 §§相关问题§§ 1. 如何修改上述代码以同时监控文件的访问(access)事件? 2. 当使用inotify监控目录时,如何区分目录自身事件和内部文件事件? 3. 如何处理inotify队列溢出(IN_Q_OVERFLOW)事件? 4. 在多线程环境下使用inotify需要注意什么? 5. 如何用inotify监控整个目录树(含子目录)的变化? </think> ### inotify使用实例详解 以下是一个完整的C语言示例,展示如何使用inotify监控目录变化并实时输出事件信息: ```c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/inotify.h> #include <unistd.h> #include <limits.h> #define EVENT_SIZE (sizeof(struct inotify_event)) #define BUF_LEN (1024 * (EVENT_SIZE + 16)) int main(int argc, char **argv) { int inotify_fd, watch_fd; char buffer[BUF_LEN]; ssize_t length; char *p; if (argc < 2) { fprintf(stderr, "用法: %s <监控目录>\n", argv[0]); exit(EXIT_FAILURE); } // 1. 创建inotify实例 inotify_fd = inotify_init(); if (inotify_fd == -1) { perror("inotify_init失败"); exit(EXIT_FAILURE); } // 2. 添加监控目录(监控所有事件) watch_fd = inotify_add_watch(inotify_fd, argv[1], IN_MODIFY | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO); if (watch_fd == -1) { perror("inotify_add_watch失败"); close(inotify_fd); exit(EXIT_FAILURE); } printf("监控目录: %s\n", argv[1]); printf("事件类型: 文件创建 | 修改 | 删除 | 移动\n"); printf("按Ctrl+C退出监控...\n"); // 3. 事件处理循环 while (1) { length = read(inotify_fd, buffer, BUF_LEN); if (length == -1 && errno != EAGAIN) { perror("读取事件失败"); break; } if (length <= 0) continue; // 4. 解析事件缓冲区 for (p = buffer; p < buffer + length;) { struct inotify_event *event = (struct inotify_event *)p; // 打印事件信息 if (event->len) { printf("事件: "); if (event->mask & IN_CREATE) printf("文件创建: %s", event->name); if (event->mask & IN_MODIFY) printf("文件修改: %s", event->name); if (event->mask & IN_DELETE) printf("文件删除: %s", event->name); if (event->mask & IN_MOVED_FROM) printf("文件移出: %s", event->name); if (event->mask & IN_MOVED_TO) printf("文件移入: %s", event->name); printf("\n"); } p += EVENT_SIZE + event->len; } } // 5. 清理资源 inotify_rm_watch(inotify_fd, watch_fd); close(inotify_fd); return EXIT_SUCCESS; } ``` ### 编译与运行: ```bash # 编译 gcc inotify_demo.c -o inotify_monitor # 运行(监控/tmp目录) ./inotify_monitor /tmp ``` ### 测试效果: 1. 新终端创建文件: ```bash touch /tmp/testfile ``` 输出:`事件: 文件创建: testfile` 2. 修改文件: ```bash echo "hello" > /tmp/testfile ``` 输出:`事件: 文件修改: testfile` 3. 移动文件: ```bash mv /tmp/testfile /tmp/newname ``` 输出: ``` 事件: 文件移出: testfile 事件: 文件移入: newname ``` ### 事件类型扩展: 可监控更多事件类型: ```c // 添加更多监控标志 watch_fd = inotify_add_watch(inotify_fd, argv[1], IN_ACCESS | // 文件访问 IN_ATTRIB | // 元数据变更 IN_CLOSE_WRITE | // 关闭可写文件 IN_OPEN | // 文件打开 IN_DELETE_SELF | // 监控目录自身被删除 IN_MOVE_SELF // 监控目录自身被移动 ); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值