今天在阅读 Android getevent源码的时候,看到inotify,有点不理解,记录一下。
Linux inotify使用教程以及解析
什么是 inotify
inotify(inode notify)是 Linux 内核提供的一种用于监控文件系统变化的机制。它允许程序监控文件系统中的文件或目录的各种事件(如文件的创建、删除、修改等),以便程序可以在这些事件发生时做出响应。
使用 inotify 的基本步骤
1.创建 inotify 实例:
使用 inotify_init() 函数创建一个 inotify 实例,它返回一个文件描述符,后续操作都通过该描述符进行。
2.添加监控项:
使用 inotify_add_watch() 函数向 inotify 实例添加需要监控的文件或目录,并指定要监控的事件类型。
3.读取事件:
使用 read() 或其他机制(如 poll 或 select)来读取事件,并对事件做出相应的处理。
4.移除监控项:
使用 inotify_rm_watch() 函数从 inotify 实例中移除监控项。
5.关闭 inotify 实例:
使用 close() 关闭 inotify 文件描述符。
主要函数
1.inotify_init()
int inotify_init(void);
这个函数创建一个 inotify 实例,返回一个文件描述符。如果出错,返回 -1 并设置 errno
2.inotify_add_watch()
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
这个函数为某个文件或目录添加监控。参数 fd 是 inotify 文件描述符,pathname 是需要监控的文件或目录路径,mask 是需要监控的事件类型。返回一个监控描述符,用于标识这个监控项。如果出错,返回 -1 并设置 errno
3.inotify_rm_watch()
int inotify_rm_watch(int fd, int wd);
这个函数移除某个监控项。参数 fd 是 inotify 文件描述符,wd 是需要移除的监控描述符。返回 0 成功,出错返回 -1 并设置 errno
4.事件结构体
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* An unique cookie associating related events (for rename(2)) */
uint32_t len; /* Size (including nulls) of name */
char name[]; /* Name (length specified by len) */
};
主要事件类型
- IN_ACCESS:文件被访问(如读操作)
- IN_MODIFY:文件被修改
- IN_ATTRIB:文件元数据改变(如权限、时间戳等)
- IN_CLOSE_WRITE:可写文件被关闭
- IN_CLOSE_NOWRITE:不可写文件被关闭
- IN_OPEN:文件被打开
- IN_MOVED_FROM:文件被移走
- IN_MOVED_TO:文件被移到某处
- IN_CREATE:文件或目录被创建
- IN_DELETE:文件或目录被删除
- IN_DELETE_SELF:自己被删除(监控的文件或目录本身被删除)
- IN_MOVE_SELF:自己被移动(监控的文件或目录本身被移动)
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
#define EVENT_SIZE (sizeof(struct inotify_event))
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
int main()
{
// 创建 inotify 实例
int inotify_fd = inotify_init();
if (inotify_fd < 0)
{
perror("inotify_init");
exit(EXIT_FAILURE);
}
// 添加监控的目录
int watch_fd = inotify_add_watch(inotify_fd, "/home/xxx/code/linux/inotifyApi", IN_CREATE | IN_DELETE | IN_MODIFY);
if (watch_fd == -1)
{
perror("inotify_add_watch");
exit(EXIT_FAILURE);
}
char buffer[EVENT_BUF_LEN];
while (1)
{
// 读取事件
int length = read(inotify_fd, buffer, EVENT_BUF_LEN);
if (length < 0)
{
perror("read");
exit(EXIT_FAILURE);
}
int i = 0;
while (i < length)
{
struct inotify_event *event = (struct inotify_event *)&buffer[i];
if (event->len)
{
if (event->mask & IN_CREATE)
{
printf("File %s was created.\n", event->name);
}
else if (event->mask & IN_DELETE)
{
printf("File %s was deleted.\n", event->name);
}
else 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);
// 关闭 inotify 文件描述符
close(inotify_fd);
return 0;
}