Bootstrap

2024-07-24 Linux C語言使用inotify进行文件变化检测

一、在Linux中,用C语言检测文件内容变化的方法有几种,最常用的包括以下几种:

  1. 轮询(Polling):周期性地读取文件并检查内容是否变化。
  2. inotify:使用Linux内核提供的inotify接口,这是一个高效且常用的方法。

二、使用inotify进行文件变化检测

  inotify是Linux内核提供的一个机制,用于监控文件系统事件。以下是一个使用inotify接口来检测文件内容变化的示例。

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

#define EVENT_SIZE (sizeof(struct inotify_event))
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))


#define MAX_LINE_LENGTH 1024

//#define FILE_PATH_NAME "/sys/class/android_usb/android0/state"
#define FILE_PATH_NAME "/data/state"


void read_first_line(const char *filename, char *line, size_t max_length) {
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    if (fgets(line, max_length, file) == NULL) {
        if (feof(file)) {
            printf("The file is empty.\n");
        } else {
            perror("fgets");
        }
        //fclose(file);
        //exit(EXIT_FAILURE);
    }

    fclose(file);
}

int main() {
    int length, i = 0;
    int fd;
    int wd;
    char buffer[EVENT_BUF_LEN];
    char line[MAX_LINE_LENGTH];
	
    // 创建inotify实例
    fd = inotify_init();
    if (fd < 0) {
        perror("inotify_init");
    }

    // 添加监控的文件
    wd = inotify_add_watch(fd, FILE_PATH_NAME, IN_MODIFY);
    printf("Listen: %s \n", FILE_PATH_NAME);
	
    while (1) {
        // 读取事件
		printf("read...................\n");
        length = read(fd, buffer, EVENT_BUF_LEN);
        if (length < 0) {
            perror("read");
        }
        printf("read end length=%d...................\n",length);
       
        i = 0;
        while (i < length) {
            struct inotify_event *event = (struct inotify_event *) &buffer[i];
			printf("event->len=%d,EVENT_SIZE=%d,IN_MODIFY=%d\n" ,event->len,EVENT_SIZE,IN_MODIFY);
            if (event->mask & IN_MODIFY) {
                printf("The file was modified.\n");
			
            memset(line,0,MAX_LINE_LENGTH);			
			read_first_line(FILE_PATH_NAME, line, MAX_LINE_LENGTH);
			
			printf("The first line is: %s \n", line);
			printf("strlen(DISCONNECTED)=%d\n",strlen("DISCONNECTED"));
			if (strncmp(line, "DISCONNECTED",strlen("DISCONNECTED")) == 0) {
               printf("usb device is disconnected!\n");
            } 
	
            }
            i += EVENT_SIZE + event->len;
        }
    }

    // 移除监控和关闭inotify实例
    inotify_rm_watch(fd, wd);
    close(fd);

    return 0;
}

三、代码解释

  1. 包含头文件:包含了必要的头文件stdio.hstdlib.hsys/inotify.hunistd.h
  2. 定义常量
    • EVENT_SIZE:单个inotify_event结构的大小。
    • EVENT_BUF_LEN:缓冲区的大小,用于存储读取到的事件。
  3. 初始化inotify实例
    • 使用inotify_init创建inotify实例。如果创建失败,打印错误信息。
  4. 添加监控的文件
    • 使用inotify_add_watch添加监控文件。这里监控文件的路径是/path/to/your/file.txt,并且监控文件的修改事件(IN_MODIFY)。
  5. 读取事件并处理
    • 使用read函数读取事件信息。如果读取失败,打印错误信息。
    • 遍历读取到的事件,检查是否包含IN_MODIFY标志。如果包含,则表示文件被修改,打印相关信息。
  6. 清理
    • 使用inotify_rm_watch移除监控。
    • 关闭inotify实例。

四、实例运行效果图。

;