讲师博文
对linux中的inotify机制的一点认识 来源 : 未知     2018-09-21

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;

}

扫码申领本地嵌入式教学实录全套视频及配套源码

上一篇:Fragment的使用

下一篇:APK之间的互相调用

400-611-6270

Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5京公海网安备11010802025203号