Linux内核API notify_change

notify_change()函数的作用是注册一个通知器,当文件的属性改变后,用来通知文件系统。改变的属性放在attr结构体中,函数首先会对传入的参数attr进行设置,使其对当前文件系统可用。struct iattr的定义见文件linux-3.19.3/include/linux/fs.h:

struct iattr {
    unsigned int            ia_valid;       /*检验是否有权限被修改*/
    umode_t                 ia_mode;        /*该节点的模式*/
    uid_t                   ia_uid;         /*所有者标识符*/
    gid_t                   ia_gid;         /*组标识符*/
    loff_t                  ia_size;        /*文件的字节数*/
    struct timespec         ia_atime;       /*上次访问文件的时间*/
    struct timespec         ia_mtime;       /*上次写文件的时间*/
    struct timespec         ia_ctime;       /*上次修改索引节点的时间*/
    struct file             *ia_file;
};

其中的字段ia_valid的值可以是下面的宏,或是几个宏进行“或”操作,定义见文件linux-3.19.3/include/linux/fs.h。

#define   ATTR_MODE                   (1<<0)
#define   ATTR_UID                    (1<<1)
#define   ATTR_GID                    (1<<2)
#define   ATTR_SIZE                   (1<<3)
#define   ATTR_ATIME                 (1<<4)
#define   ATTR_MTIME                 (1<<5)
#define   ATTR_CTIME                 (1<<6)
#define   ATTR_ATIME_SET            (1<<7)
#define   ATTR_MTIME_SET            (1<<8)
#define   ATTR_FORCE                 (1<<9)
#define   ATTR_ATTR_FLAG            (1<<10)
#define   ATTR_KILL_SUID            (1<<11)
#define   ATTR_KILL_SGID            (1<<12)
#define   ATTR_FILE                   (1<<13)
#define   ATTR_KILL_PRIV            (1<<14)
#define   ATTR_OPEN                   (1<<15)
#define   ATTR_TIMES_SET            (1<<16)

notify_change文件包含

#include <linux/fs.h>

notify_change函数定义

在内核源码中的位置:linux-3.19.3/fs/attr.c

函数定义格式:

int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)

notify_change输入参数说明

  • dentry:发生改变后的inode结构体所在的目录dentry结构体变量,其定义及详细说明参考极客笔记中d_alloc ()函数的参数说明部分。
  • attr:包含需要改变inode结构体的各个字段修改信息的iattr结构体。其字段包括所有者标识符、组标识符、文件的字节数、上次访问文件的时间、上次写文件的时间、上次修改索引节点的时间等。
  • delegated_inode:struct inode类型结构体变量的指针,如果inode的属性被更改,新的信息将会保存在delegated_inode中,其定义及详细说明参考极客笔记中d_find_alias()函数的参数说明部分。

notify_change返回参数说明

  • notify_change()函数的返回结果是int型的变量,可能的取值是0或-1,若返回0,则表示已经给文件系统成功发送了提示信息;返回-1,则说明发送的提示信息没有成功。其中,-1表示返回值的错误标志是-EPERM,而EPERM宏在linux-3.19.3/include/asm-generic/errno-base.h文件中被定义,值为1,含义为操作不被允许。

notify_change实例解析

编写测试文件:notify_change.c

头文件声明如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/path.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");

定义变量:

struct iattr attr=
{
    . ia_atime.tv_sec = 0
};

模块初始化函数:

int notify_change_init(void)
{
    struct dentry *dentry;
    struct inode * node = (struct inode*)(kmalloc(sizeof(struct inode), GFP_KERNEL));
    dentry = current->fs->pwd.dentry;     //获取当前文件的入口目录
    printk("attr.ia_atime.tv_sec = %ld\n", attr.ia_atime.tv_sec); //显示属性的时间值
    int res = notify_change(dentry, &attr, &node);                  //改变当文件的属性
    printk("The returned value of \"notify_change\" is %d.\n", res);
                                          //显示函数notify_change()的返回结果
    printk("attr.ia_atime.tv_sec = %ld\n", attr.ia_atime.tv_sec); //显示属性的时间值
    kfree(node);
    return 0;
}

模块退出函数:

void notify_change_exit(void)
{
    printk("Goodbye notify_change\n");
}

模块初始化及退出函数调用:

module_init(notify_change_init);
module_exit(notify_change_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod notify_change.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。

Linux内核API notify_change

结果分析:

预先设置iattr结构体的访问时间属性为0,然后通过notify_change()函数注册属性改变通知器,再次显示iattr结构体的访问时间属性,notify_change()函数的返回值为0,说明通知器注册成功,同时,iattr内部的字段值也发生了变化,时间字段值变为与当前系统同步。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程