简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
- 🌻1.前言
- 🌻2.Linux内核之fsnotify_create介绍
- 🐓2.1 问题一:新的文件或目录是被谁创建的?为什么要通知文件系统?
- 🐓2.2 问题二:内核空间创建文件或目录要通知文件系统吗?内核和文件系统是什么关系?
- 🌻3.代码实例
- 🐓3.1 监视文件创建并记录到内核日志
- 🐓3.2 实时监控文件系统中的新文件并通知用户空间程序
- 🐓3.3 监控文件创建并触发定时器
🌻1.前言
本篇目的:Linux内核之内核通知文件系统创建的路径:fsnotify_create用法实例
🌻2.Linux内核之fsnotify_create介绍
-
fsnotify_create 函数是 Linux 内核中的一个函数,用于通知文件系统中的文件或目录创建事件。当新的文件或目录被创建时,内核会调用 fsnotify_create 函数来向文件系统通知机制注册相应的创建事件监听器。
-
函数实现:
static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
{// 审计文件系统事件:通知有新的子节点被创建audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);// 发送文件系统通知事件:文件被创建fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
}
-
参数说明:
inode:新创建的文件或目录所属的父目录的索引节点。
dentry:新创建的文件或目录的目录项(dentry)。 -
函数作用:
-
审计文件系统事件: 调用 audit_inode_child 函数来进行文件系统事件的审计记录。这个步骤通常用于记录文件系统中的重要操作,如文件的创建、删除等。在这里,它记录了一个子节点的创建事件。
-
发送文件系统通知事件: 调用 fsnotify 函数来发送文件系统通知事件。这个事件通知了文件系统的监听器,有一个新的文件或目录被创建。通常,文件系统通知机制会通过注册监听器的方式来监视文件系统中的特定事件,并在事件发生时通知相关的监听器。
实现意义: -
fsnotify_create 函数的主要作用是向文件系统通知机制注册新创建文件或目录的事件监听器。通过调用这个函数,内核可以通知文件系统的监听器,以便它们能够在文件或目录创建时执行相应的操作。这个函数是文件系统通知机制的一部分,用于提供文件系统的监视和通知功能,以实现文件系统的高级功能,如实时监控、日志记录等。
🐓2.1 问题一:新的文件或目录是被谁创建的?为什么要通知文件系统?
-
新的文件或目录通常是由用户空间的应用程序或者其他内核模块创建的。例如,一个用户可以通过命令行工具或者图形化文件管理器创建文件或目录。另外,内核模块也有可能通过系统调用或其他方式创建文件或目录。
-
通知文件系统的目的在于让文件系统的其他部分或者用户空间的程序知晓文件系统的变化。这样做有几个主要原因:
-
实时监控: 文件系统通知机制允许程序实时监控文件系统的变化,例如文件或目录的创建、修改、删除等操作。这对于需要实时监控文件系统状态的应用程序非常有用,如文件同步工具、实时备份程序等。
-
自动化处理: 文件系统通知机制可以触发自动化处理,让程序根据文件系统的变化执行相应的操作。例如,当有新文件创建时,可以自动对其进行备份或者转码处理。
-
日志记录和审计: 文件系统通知机制可以用于记录文件系统中的重要操作,如文件的创建、修改、删除等。这对于系统管理员进行日志记录和审计非常重要,可以帮助追踪文件系统操作的来源和时间。
-
综上所述,通知文件系统的目的是为了让系统的其他部分或者用户空间的程序能够及时了解文件系统的变化,从而进行相应的处理、监控或记录。这对于实现文件系统的实时监控、自动化处理和日志记录非常重要。
🐓2.2 问题二:内核空间创建文件或目录要通知文件系统吗?内核和文件系统是什么关系?
-
内核空间创建文件或目录时,通常是由内核中的某个模块、驱动程序或者内核线程进行的。
-
通知文件系统: 内核空间创建文件或目录时,通常需要通知文件系统,以便文件系统能够更新自身的数据结构,并在需要时通知其他部分或用户空间的程序。这种通知机制通常通过文件系统提供的相应接口或者文件系统通知机制来实现。
-
关系: 内核和文件系统之间的关系可以理解为内核是文件系统的基础,文件系统则是内核的一个重要模块。文件系统是内核提供的一种机制,用于组织和管理存储在存储介质上的文件和目录。在 Linux 内核中,文件系统由一系列的数据结构、算法和接口组成,用于实现文件的存储、访问和管理等功能。内核空间的其他模块和驱动程序可以利用文件系统提供的接口和机制来进行文件的创建、读写、删除等操作。因此,内核和文件系统是相互依赖、相互作用的关系。
-
总之,内核空间创建文件或目录时通常需要通知文件系统,以维护文件系统的一致性和完整性。内核和文件系统之间是相互依赖、相互作用的关系,文件系统是内核提供的重要功能之一,用于管理存储在存储介质上的文件和目录。
🌻3.代码实例
🐓3.1 监视文件创建并记录到内核日志
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/fsnotify.h>// 文件创建事件处理函数
static void file_create_event(struct inode *inode, struct dentry *dentry)
{// 记录文件创建事件到内核日志pr_info("File created: %s\n", dentry->d_name.name);
}// 文件创建函数
static int myfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
{// 调用 fsnotify_create 函数注册文件创建事件监听器fsnotify_create(dir, dentry);// 处理文件创建事件file_create_event(dir, dentry);return 0;
}// 文件操作结构体
static const struct file_operations myfs_file_operations = {.create = myfs_create,
};// 模块初始化函数
static int __init myfs_init(void)
{// 注册文件系统register_filesystem(&myfs_type);return 0;
}// 模块退出函数
static void __exit myfs_exit(void)
{// 注销文件系统unregister_filesystem(&myfs_type);
}module_init(myfs_init);
module_exit(myfs_exit);MODULE_LICENSE("GPL");
🐓3.2 实时监控文件系统中的新文件并通知用户空间程序
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/fsnotify.h>
#include <net/sock.h>
#include <linux/netlink.h>#define NETLINK_MYFS 31static struct sock *nl_sk = NULL;// 发送 Netlink 消息到用户空间
static void send_netlink_message(const char *msg)
{struct sk_buff *skb;struct nlmsghdr *nlh;int msg_size = strlen(msg) + 1;int res;if (!nl_sk)return;skb = nlmsg_new(NLMSG_ALIGN(msg_size), GFP_KERNEL);if (!skb) {pr_err("Failed to allocate skb\n");return;}nlh = nlmsg_put(skb, 0, 0, 0, msg_size, 0);strncpy(nlmsg_data(nlh), msg, msg_size);res = nlmsg_unicast(nl_sk, skb, 0);if (res < 0)pr_err("Error while sending message to user space\n");
}// 文件创建事件处理函数
static void file_create_event(struct inode *inode, struct dentry *dentry)
{char msg[256];snprintf(msg, sizeof(msg), "New file created: %s\n", dentry->d_name.name);// 发送 Netlink 消息通知用户空间程序send_netlink_message(msg);
}// 文件创建函数
static int myfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
{// 调用 fsnotify_create 函数注册文件创建事件监听器fsnotify_create(dir, dentry);// 处理文件创建事件file_create_event(dir, dentry);return 0;
}// 文件操作结构体
static const struct file_operations myfs_file_operations = {.create = myfs_create,
};// 模块初始化函数
static int __init myfs_init(void)
{struct netlink_kernel_cfg cfg = {.input = NULL,};nl_sk = netlink_kernel_create(&init_net, NETLINK_MYFS, &cfg);if (!nl_sk) {pr_err("Failed to create netlink socket\n");return -ENOMEM;}// 注册文件系统register_filesystem(&myfs_type);return 0;
}// 模块退出函数
static void __exit myfs_exit(void)
{// 注销文件系统unregister_filesystem(&myfs_type);// 释放 Netlink 套接字netlink_kernel_release(nl_sk);
}module_init(myfs_init);
module_exit(myfs_exit);MODULE_LICENSE("GPL");
🐓3.3 监控文件创建并触发定时器
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/fsnotify.h>
#include <linux/timer.h>#define TIMER_INTERVAL (5 * HZ)static struct timer_list myfs_timer;// 文件创建事件处理函数
static void file_create_event(struct inode *inode, struct dentry *dentry)
{pr_info("New file created: %s\n", dentry->d_name.name);
}// 定时器回调函数
static void myfs_timer_callback(struct timer_list *timer)
{// 定时器触发时的处理操作,例如检查文件系统中的新文件
}// 文件创建函数
static int myfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
{// 调用 fsnotify_create 函数注册文件创建事件监听器fsnotify_create(dir, dentry);// 处理文件创建事件file_create_event(dir, dentry);return 0;
}// 文件操作结构体
static const struct file_operations myfs_file_operations = {.create = myfs_create,
};// 模块初始化函数
static int __init myfs_init(void)
{// 初始化定时器setup_timer(&myfs_timer, myfs_timer_callback, 0);// 设置定时器mod_timer(&myfs_timer, jiffies + TIMER_INTERVAL);// 注册文件系统register_filesystem(&myfs_type);return 0;
}// 模块退出函数
static void __exit myfs_exit(void)
{// 删除定时器del_timer(&myfs_timer);// 注销文件系统unregister_filesystem(&myfs_type);
}module_init(myfs_init);
module_exit(myfs_exit);MODULE_LICENSE("GPL");