Linux监听器 -- inotify

news2024/9/21 2:51:12

inotify作为Linux系统的一个监听器,能够监听文件或者目录的变化。

inotify接口

inotify的接口主要有三个,分别是inotify_init、inotify_add_watch 和 inotify_rm_watch。下面分别进行详细介绍。
inotify_init 函数用于创建inotify句柄,函数原型int inotify_init(void);
inotify_add_watch 负责添加监听的文件或者目录,函数原型int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
fd: inotify_init 创建的inotify句柄。
pathname: 要监听的文件或者目录路径。
mask: 要监听的事件类型。
在这里插入图片描述
inotify_rm_watch 用于删除被监听的文件或者目录,函数原型int inotify_rm_watch(int fd, int wd);
fd: inotify_init 创建的inotify句柄。
wd: inotify_add_watch 创建的句柄

inotify使用

结构体 inotify_event 主要用于保存被监听文件或目录的信息,具体定义如下。
在这里插入图片描述
实现一个基于inotify的简单例子,代码如下。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/inotify.h>
#include <pthread.h>

#define EVENTS_BUF_SIZE 1024

static void PrintEvent(const char *base, struct inotify_event *event)
{
    char *operate;
    int mask = event->mask;

    if (mask & IN_ACCESS)        operate = "ACCESS";
    if (mask & IN_ATTRIB)        operate = "ATTRIB";
    if (mask & IN_CLOSE_WRITE)   operate = "CLOSE_WRITE";
    if (mask & IN_CLOSE_NOWRITE) operate = "CLOSE_NOWRITE";
    if (mask & IN_CREATE)        operate = "CREATE";
    if (mask & IN_DELETE_SELF)   operate = "DELETE_SELF";
    if (mask & IN_MODIFY)        operate = "MODIFY";
    if (mask & IN_MOVE_SELF)     operate = "MOVE_SELF";
    if (mask & IN_MOVED_FROM)    operate = "MOVED_FROM";
    if (mask & IN_MOVED_TO)      operate = "MOVED_TO";
    if (mask & IN_OPEN)          operate = "OPEN";
    if (mask & IN_IGNORED)       operate = "IGNORED";
    if (mask & IN_DELETE)        operate = "DELETE";
    if (mask & IN_UNMOUNT)       operate = "UNMOUNT";

    printf("%s: %s\n", base, operate);
}

static void Thread_Inotify(void *arg)
{
    char *path = (char *)arg;
    char events[EVENTS_BUF_SIZE];
    int fd = inotify_init();  // 创建 inotify 句柄
    if (fd < 0) {
        printf("Failed to initalize inotify\n");
        return;
    }
    int ret = inotify_add_watch(fd, path, IN_ALL_EVENTS);   // 添加监听事件类型
    if (ret == -1) {
        printf("Failed to add file or directory watch\n");
        return;
    }

    while (1) {
        memset(events, 0, sizeof(events));

        int nbytes = read(fd, events, sizeof(events));
        if (nbytes <= 0) {
            printf("Failed to read events\n");
            continue;
        }

        int offset = 0;
        struct inotify_event event;
        do {
            memset(&event, 0x00, sizeof(event));
            memcpy(&event, &events[offset], sizeof(event));
            PrintEvent(path, &event);
            offset += sizeof(struct inotify_event) + event.len;
        } while (offset < nbytes);
    }  
}

static void Thread_HandleFile(void *arg)
{
    char *path = (char *)arg;
    while (1)
    {
        FILE *fp = fopen(path, "wb+");
        char wbuf[] = "123";
        fwrite(wbuf, sizeof(wbuf), sizeof(char), fp);
        fclose(fp);

        sleep(2);

        fp = fopen(path, "r");
        char rbuf[16];
        fread(rbuf, sizeof(rbuf), sizeof(char), fp);
        fclose(fp);
        
        sleep(2);
        break;
    }
}

int main(int argc, char *argv[])
{
    char *path = argv[1];
    pthread_t thid_inotify, thid_handle;

    pthread_create(&thid_inotify, NULL, (void *)Thread_Inotify, path);

    sleep(2);

    pthread_create(&thid_handle, NULL, (void *)Thread_HandleFile, path);

    while (1) {
        sleep(2);
    }

    return 0;
}

inotify原理

以read为例进行说明,当用户调用read时,内核会将事件保存在inotify_device中的队列events(struct list_head events;)中,然后唤醒等待该events的进程(wait_queue_head_t wq;)。具体的调用关系如下图:
在这里插入图片描述
当用户调用读写等系统调用时,内核会创建相应的触发函数来产生一个事件,并将该事件添加到inotify_device的事件队列events中,并唤醒等待该事件的进程。当进程被唤醒,便可以通过read来读取inotify事件队列中的事件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512090.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一图看懂 pytz 模块:现代以及历史版本的世界时区定义数据库,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pytz 模块&#xff1a;现代以及历史版本的世界时区定义&#xff0c;将时区数据库引入 Python&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&am…

算法小课堂(七)字符串

一、概念 1.1相关概念 0C中有两种字符串表示形式&#xff1a;C风格字符串和string类类型。 C风格字符串是 字符数组使用null字符\0终止的一维字符数组&#xff0c;字符指针是一个指针变量&#xff0c;里面存放一个字符的地址 而string类处理起字符串来会方便很多&#xff0c;完…

Golang中的数组和切片

目录 数组 基础知识 声明并初始化一个数组 遍历一个数组 切片 基础知识 声明并初始化一个切片 向切片中添加元素 切片的遍历和切片表达式 数组和切片的区别 数组 基础知识 数组是一种由固定长度的特定类型元素组成的序列&#xff0c;元素可以是任何数据类型&#x…

数组——知识点大全(简洁,含使用演示和代码)

目录 一.一维数组的创建 1.数组的基本形式 2.变长数组 3.数组的初始化 二.数组的本质 三.一维数组的使用 1.访问数组成员 2.计算数组的大小 四.一维数组在内存中的存储 五.二维数组 1.二维数组的形式 2.二维数组的初始化规则 六.二维数组的使用 1.打印二维数组 …

Linux下新加新磁盘分区及挂载

一&#xff1a;新插入磁盘查看 查看插入磁盘 法1&#xff1a;$sudo fdisk -l 法2&#xff1a; $sudo lsblk 二&#xff1a;磁盘分区及格式化 1: 分区 $sudo fdisk /dev/nvme0n1 进入分区工具后&#xff0c;我们可以输入 m 看指令说明&#xff1a; Command (m for help): …

前端框架比较:Vue.js、React、AngularJS三者的优缺点和应用场景

章节一&#xff1a;引言 在当前的互联网开发中&#xff0c;前端框架已经成为了不可或缺的一部分。然而&#xff0c;前端框架如此之多&#xff0c;该如何选择呢&#xff1f;Vue.js、React和AngularJS是目前比较受欢迎的三个前端框架&#xff0c;它们各自有着不同的优缺点和应用…

MySQL笔记(三) 联结、组合查询、全文本搜索、视图、索引、触发器、事务

文章目录 联结关系表为什么要使用联结维护引用完整性 内部联结联结多个表创建高级联结使用表别名 自联接自然联结外部联结 OUTER JOIN外部联结的类型 使用带聚集函数的联结要点 组合查询 UNION创建规则注意 全文本搜索查询拓展布尔文本搜索总结 视图为什么使用视图视图的规则和…

虚拟机与主机互传文件方法分享

现在虚拟机的使用已经非常普及&#xff0c;无论新手学习&#xff0c;还是运维工程师搭建虚拟化平台&#xff0c;都会使用到虚拟机。对个人用户来说&#xff0c;非常方便就能搭建很多操作系统进行学习&#xff1b;对企业用户来说更是降低了服务器的硬件成本。 使用虚拟机的时候…

本周日直播,全链路数据治理实践论坛开放报名

5月14日&#xff0c;09:00-12:00&#xff0c;由阿里云资深技术专家温绍锦老师出品的 DataFun Summit 2023&#xff1a;数据治理在线峰会-全链路数据治理论坛&#xff0c;将邀请来自阿里、Aloudata大应科技、爱奇艺的4位专家就相关主题进行深度分享&#xff0c; 出品人&#xff…

JAVA-继承

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 目录 文章目录 前言 1.为什么需要继承 2. 继承的语法 3.子类构造方法 4.super和this的异同 5.final 关键字 总结 前言 继承是面向对象语法的三大特征之一。在以后写…

【Python 装饰器成长路径】零基础也能轻松掌握的学习路线与参考资料

Python装饰器是Python语言的一个重要特性&#xff0c;可以让代码更加简洁、优雅&#xff0c;并且让代码重用性更加高效。本文针对Python装饰器的学习路线&#xff0c;参考资料和优秀实践进行详细介绍。 文章目录 一、学习路线二、参考资料三、优秀实践 一、学习路线 了解函数…

10. 类的友元

一、类的友元 生活中你的家有客厅&#xff08;public&#xff09;&#xff0c;有你的卧室&#xff08;private&#xff09;&#xff0c;客厅所有来的客人都可以进去&#xff0c;但是你的卧室是私有的&#xff0c;也就是说只有你能进去&#xff0c;但是&#xff0c;你也可以允许…

01-mysql安装篇(rpm方式安装+压缩包安装)

文章目录 一、rpm方式安装1、检查是否安装了mariadb2、下载mysql3、上传解压4、安装5、检查安装6、开启mysql服务7、登陆mysql8、修改密码设置规则&#xff08;简单型-学习用&#xff09;9、修改密码10、授权远程登陆11、启停mysql命令12、rpm方式安装说明 二、压缩包方式安装V…

前端技术搭建飞机大战小游戏(内含源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分 ✨ 写在前面 上周我们实通过前端基础实现了弹珠游戏&#xff0c;当然很多伙伴再评论区提出了想法&#xff0c;后续我们会考虑实现的&#xff0c;今天还是继续按照我们原定的节…

2023年第三届长三角高校数学建模竞赛】A 题 快递包裹装箱优化问题 详细数学建模过程

1 题目 2022 年&#xff0c;中国一年的包裹已经超过 1000 亿件&#xff0c;占据了全球快递事务量的一半以上。近几年&#xff0c;中国每年新增包裹数量相当于美国整个国家一年的包裹数量&#xff0c; 十年前中国还是物流成本最昂贵的国家&#xff0c;当前中国已经建立起全世界…

阿里云服务器建站教程来了(十分钟网站上线)

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流程&#xff1a; …

布朗运动模拟

布朗运动模拟 文章目录 布朗运动模拟[toc]1 布朗运动定义2 布朗运动模拟3 布朗桥4 带漂移布朗运动5 几何布朗运动 1 布朗运动定义 给定随机过程 { W ( t ) , t ≥ 0 } \{W(t),t \ge 0 \} {W(t),t≥0}&#xff0c;满足以下条件&#xff0c;则称 W ( t ) W(t) W(t)为标准布朗运动…

1 ElasticSearch介绍

全文检索 Elastisearch 研究 目标 了解Elasticsearch的应用场景掌握索引维护的方法掌握基本的搜索Api的使用方法 约束 阅读本教程之前需要掌握Lucene的索引方法、搜索方法 。 1 ElasticSearch介绍 1.1 介绍 官方网址&#xff1a;https://www.elastic.co/cn/products/elas…

【OpenCV】学习课-图像获取与显示(1)!

OpenCV是一个基于Apache2.0许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1] 它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLA…

JAVA-多态

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 目录 文章目录 1.多态的概念 2.多态的实现条件 3.重写 总结 1.多态的概念 什么是多态? 通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个…