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