今天的主要内容很少,昨天我们把目录的处理换成我们指定的sfs之类的操作,今天则是涉及自定义文件操作。
源码解析
新增的代码只有inode.c中的一部分:
struct inode_operations sfs_file_inode_ops = {
.getattr = simple_getattr,
};
之后在super.c中也仅仅是加上了对sfs_file_inode_ops的声明,同时在samplefs_get_inode中,当mode为S_IFREG即处理常规文件时,将i_op替换为sfs_file_inode_ops。
不妨来看一看libfs.c中的simple_getattr函数:
int simple_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int query_flags)
{
struct inode *inode = d_inode(path->dentry);
generic_fillattr(inode, stat);
stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9);
return 0;
}
EXPORT_SYMBOL(simple_getattr);
代码很短,不妨逐行解释。
d_inode的解释是:
Get the actual inode of this dentry
很简单,就是获取某个dentry的inode,dcache.h中对d_inode的实现为:
static inline struct inode *d_inode(const struct dentry *dentry)
{
return dentry->d_inode;
}
在fs/stat.c中,generic_fillattr定义如下:
/**
* generic_fillattr - Fill in the basic attributes from the inode struct
* @inode: Inode to use as the source
* @stat: Where to fill in the attributes
*
* Fill in the basic attributes in the kstat structure from data that's to be
* found on the VFS inode structure. This is the default if no getattr inode
* operation is supplied.
*/
void generic_fillattr(struct inode *inode, struct kstat *stat)
{
stat->dev = inode->i_sb->s_dev;
stat->ino = inode->i_ino;
stat->mode = inode->i_mode;
stat->nlink = inode->i_nlink;
stat->uid = inode->i_uid;
stat->gid = inode->i_gid;
stat->rdev = inode->i_rdev;
stat->size = i_size_read(inode);
stat->atime = inode->i_atime;
stat->mtime = inode->i_mtime;
stat->ctime = inode->i_ctime;
stat->blksize = i_blocksize(inode);
stat->blocks = inode->i_blocks;
if (IS_NOATIME(inode))
stat->result_mask &= ~STATX_ATIME;
if (IS_AUTOMOUNT(inode))
stat->attributes |= STATX_ATTR_AUTOMOUNT;
}
EXPORT_SYMBOL(generic_fillattr);
注释写的很清楚,就是把inode中的一些属性复制到kstat中,kstat定义在stat.h中,初步看来是inode的一个小副本,包含了一些inode的基本信息。
struct kstat {
u32 result_mask; /* What fields the user got */
umode_t mode;
unsigned int nlink;
uint32_t blksize; /* Preferred I/O size */
u64 attributes;
u64 attributes_mask;
#define KSTAT_ATTR_FS_IOC_FLAGS \
(STATX_ATTR_COMPRESSED | \
STATX_ATTR_IMMUTABLE | \
STATX_ATTR_APPEND | \
STATX_ATTR_NODUMP | \
STATX_ATTR_ENCRYPTED \
)/* Attrs corresponding to FS_*_FL flags */
u64 ino;
dev_t dev;
dev_t rdev;
kuid_t uid;
kgid_t gid;
loff_t size;
struct timespec64 atime;
struct timespec64 mtime;
struct timespec64 ctime;
struct timespec64 btime; /* File creation time */
u64 blocks;
};
在inode中i_mapping指向该inode相关的页缓存的地址空间,内核中用address_space结构表示地址空间这一概念,nrpages成员表示缓存页的总数,PAGE_SHIFT在page.h中,页大小为4KB,PAGE_SHIFT为12,这行代码修改了一下stat->blocks的值,可能的意思是,stat->blocks表示的是文件用块表示的最大长度,但是这个9具体指什么还暂时不清楚。
以上就是getattr成员的函数解析,总体上来看就是填充了一个kstat结构,根据ppt上给出的预期结果,ls命令涉及的系统调用很可能需要getattr和kstat结构的支持。
结果和问题

可见,ls命令可以正常使用。
问题:touch命令有时会出现问题,而且与材料给出的预期结果不一致,touch命令也可以正常使用。而且时间戳的获取还是存在问题,目前使用的是:
struct timespec64 ts;
ktime_get_ts64(&ts);
inode->i_mtime = ts;
还是不能获取正确的时间戳。
本文解析了自定义文件系统的inode操作,重点介绍了sfs_file_inode_ops的实现细节,包括getattr函数的工作原理及其与kstat结构的关系,对于理解Linux内核中的文件系统操作具有重要意义。
1万+

被折叠的 条评论
为什么被折叠?



