Linux中一切皆文件,在应用程序中,有时候我们需要对文件系统的目录或者文件进行监控,以便于我们能根据文件系统的变化来做相应的后续操作。那我们如何有效的对文件系统进行监控呢?不用苦恼,linux的前辈们已经给我们做好了,在linux2.6内核中开始引入,作为linux的系统调用来使用,所以我们就可以用它来帮助我们来完成这件事了。
接下来我们来学习一下于inotify相关的系统调用接口:
int inotify_init(void);
功能:获得一个文件描述符,用于关联后续的inotify事件队列。
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
功能:在inotify文件描述符中添加新的监听对象。
参数: fd, inotify_init函数的返回值
Pathname, 添加要监听的文件或者目录的路径
Mask, 要监听的文件或者目录上发生的事件。
返回值:就是新添加监听的文件描述符。
int inotify_rm_watch(int fd, int wd);
功能:从inotify的事件队列中删除一个监听对象。
参数:fd, 监听事件描述符,就是inotify_init的返回值
wd, inotify_add_watch的返回值。
有了上边的这三个函数,我们我们就可以添加对文件或者目录的监听事件了,但是文件或者目录一旦发生了变化我们又怎么能直到呢?所以我们仅仅有他们还不够,我们还需要read函数。因为当我们添加了监听事件后,我们需要使用select或者其他的方式来监听我们的监听队列,一旦发生变化,我们就必须得用read函数读取该描述符的数据,其中的数据就包含了我们文件的变化。read的返回值就是一个或者多个struct inotify_event的结构体,结构体的定义如下:
struct inotify_event
{
int wd; /* Watch descriptor. */
uint32_t mask; /* Watch mask. */
uint32_t cookie; /* Cookie to synchronize two events. */
uint32_t len; /* Length (including NULs) of name. */
char name __flexarr; /* Name. */
};
示例代码如下:
#define BUF_LEN 10 * (sizeof(struct inotify_event) + NAME_MAX + 1)
#define WATCH_DIR_1 "/home/ys/test_1"
#define WATCH_DIR_2 "/home/ys/test_2"
int main(int argc, const char *argv[])
{
int init_fd;
int watch_fd_1, watch_fd_2;
int watch_mask = IN_ALL_EVENTS;
struct inotify_event *even;
char buf[BUF_LEN] = {0};
char *p = NULL;
ssize_t bytes;
//创建监听文件描述符句柄
init_fd = inotify_init();
if (init_fd < 0)
{
perror("fail to inotify_init");
exit(1);
}
//添加监听的目录或者文件
watch_fd_1 = inotify_add_watch(init_fd, WATCH_DIR_1, watch_mask);
if (watch_fd_1 < 0)
{
perror("fail to inotify_add_watch 111");
exit(1);
}
//添加监听的目录或者文件
watch_fd_2 = inotify_add_watch(init_fd, WATCH_DIR_2, watch_mask);
if (watch_fd_2 < 0)
{
perror("fail to inotify_add_watch 222");
exit(1);
}
fd_set readfds, tempfds;
int maxfd, i = 0;
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
//监听init_fd
FD_SET(init_fd, &readfds);
maxfd = init_fd;
tempfds = readfds;
while (1)
{
tempfds = readfds;
if (select(maxfd + 1, &tempfds, NULL, NULL, NULL) < 0)
{
perror("fail to select");
break;
}
for (i = 0; i < maxfd + 1; i++)
{
if (FD_ISSET(i, &tempfds))
{
//从init_fd中读取结构体
bytes = read(i, buf, BUF_LEN);
if (bytes < 0)
continue;
for (p = buf; p < buf + bytes;)
{
//转换成inotify_event结构体
even = (struct inotify_event *)p;
if (even->mask & IN_CREATE)
{
if (even->wd == watch_fd_1)
printf("create new file: [%s] in %s\n", even->name, WATCH_DIR_1);
else if (even->wd == watch_fd_2)
printf("create new file: [%s] in %s\n", even->name, WATCH_DIR_2);
}
else if (even->mask & IN_DELETE)
{
if (even->wd == watch_fd_1)
printf("delete [%s] from %s\n", even->name, WATCH_DIR_1);
else if (even->wd == watch_fd_2)
printf("delete [%s] from %s\n", even->name, WATCH_DIR_2);
}
else if (even->mask & IN_IGNORED)
{
if (even->wd == watch_fd_1)
printf("%s was deleted!\n", WATCH_DIR_1);
else if (even->wd == watch_fd_2)
printf("%s was deleted!\n", WATCH_DIR_2);
inotify_rm_watch(init_fd, even->wd);
}
//p指针向后的偏移
p += sizeof(struct inotify_event) + even->len;
}
}
}
}
//删除监听的描述符
inotify_rm_watch(init_fd, watch_fd_1);
inotify_rm_watch(init_fd, watch_fd_2);
close(init_fd);
close(watch_fd_1);
close(watch_fd_2);
return 0;
}
Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5,京公海网安备11010802025203号