Linux内核API generic_fillattr

generic_fillattr()函数的功能是初始化struct kstat结构体变量(在这里,kstat是kernel state的缩写,即内核状态),分别将inode结构体中各字段的值赋给kstat相应的字段。

generic_fillattr文件包含

#include <linux/fs.h>

generic_fillattr函数定义

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

函数定义格式:

void generic_f illattr(struct inode *inode, struct kstat *stat)

generic_fillattr输入参数说明

  • inode:要进行赋值操作的inode结构体。对于inode结构体,其定义及详细说明参考极客笔记中d_find_alias()函数的参数说明部分。
  • stat:要被赋值进行初始化的kstat结构体。结构体具体定义见文件linux-3.19.3/include/linux/stat.h,如下:
struct kstat {
    u64 ino;                        /*64位的*/
    dev_t dev;                      /*设备号*/
    umode_t        mode;            /*模式*/
    unsigned int nlink;             /*硬链接的数目*/
    uid_t uid;                      /*所有者标识符*/
    gid_t gid;                      /*组标识符*/
    dev_t rdev;                     /*实设备标识符*/
    loff_t size;                    /*字节数*/
    struct timespec atime;          /*上次访问kstat的时间*/
    struct timespec mtime;          /*上次写kstat的时间*/
    struct timespec ctime;          /*上次修改kstat的时间*/
    unsigned long blksize;          /*块的大小*/
    unsigned long long blocks;      /*块的数目*/
};

generic_fillattr返回参数说明

  • generic_fillattr()函数无返回值。

generic_fillattr实例解析

编写测试文件:generic_fillattr.c

头文件声明如下:

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

自定义kstat结构体:

struct kstat stat=
{
    .nlink = 0,
};

模块初始化函数:

int generic_fillattr_init(void)
{
    struct dentry *dentry;
    struct inode *inode;
    dentry = current->fs->pwd.dentry;
    inode = dentry->d_inode;

    // 输出原状态信息
    printk("Before \"generic_fillattr\", stat.dev = %d\n", stat.dev);
    printk("Before \"generic_fillattr\", stat.ino = %d\n", stat.ino);
    printk("Before \"generic_fillattr\", stat.mode = %d\n", stat.mode);
    printk("Before \"generic_fillattr\", stat.nlink = %d\n", stat.nlink);
    printk("Before \"generic_fillattr\", stat.uid = %d\n", stat.uid);
    printk("Before \"generic_fillattr\", stat.gid = %d\n", stat.gid);

    // inode结构体中的各字段的值赋给stat相应的字段
    generic_fillattr(inode, &stat);

    //输出执行完generic_fillattr()后的状态信息,并对比输出
    printk("inode->i_sb->s_dev = %d\n", inode->i_sb->s_dev);
    printk("inode->i_ino = %d\n", inode->i_ino);
    printk("inode->i_mode = %d\n", inode->i_mode);
    printk("inode->i_nlink = %d\n", inode->i_nlink);
    printk("inode->i_uid = %d\n", inode->i_uid);
    printk("inode->i_gid = %d\n", inode->i_gid);

    printk("After \"generic_fillattr\", stat.dev = %d\n", stat.dev);
    printk("After \"generic_fillattr\", stat.ino = %d\n", stat.ino);
    printk("After \"generic_fillattr\", stat.mode = %d\n", stat.mode);
    printk("After \"generic_fillattr\", stat.nlink = %d\n", stat.nlink);
    printk("After \"generic_fillattr\", stat.uid = %d\n", stat.uid);
    printk("After \"generic_fillattr\", stat.gid = %d\n", stat.gid);
    return 0;
}

模块退出函数:

void generic_fillattr_exit(void)
{
    printk("Goodbye generic_fillattr\n");
}

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

module_init(generic_fillattr_init);
module_exit(generic_fillattr_exit);

实例运行结果及分析:

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

Linux内核API generic_fillattr

结果分析:

首先将kstat结构体初始化,使其获得部分内核空间的内存。在generic_fillattr()函数执行之前显示kstat结构体部分字段的值,然后执行generic_fillattr()函数,接着分别显示传入参数的inode中和kstat结构体部分字段的值,由结果可知,两个结构体之间相对应的值都相同,即kstat结构体已经被赋值。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程