exFAT文件系统2
搜索exfat资料时,找到一篇老外的反编译exfat的文件,对我们学习代码很有帮助
文章名是reverse-engineering-microsoft-exfat-file-system_33274.pdf。
至于exfat的文件系统代码,可以从github上获取到,github地址是:https://github.com/dorimanx/exfat-nofuse
结合资料和code开启我的exfat之旅
获取到exfat-nofuse代码后,先看看代码中自带的README.md文档,check发现该开源代码是在linux系统中以命令modprobe exfat方式load the driver manually,然后使用标准的mount加载exfat文件系统。
modprobe exfat的控制主要是运行代码exfat_super.c中module_init(init_exfat_fs)的函数。
init_exfat_fs函数主要功能:
1. FsInit------exfat文件系统全局变量初始化以及一些文件系统定义边界检查
2.exfat_init_inodecache------exfat文件系统创建专属的高速缓冲
3.register_filesystem(&exfat_fs_type)------注册exfat文件系统到linux的VFS系统体系中
相关code如下:
static int __init init_exfat_fs(void)
{
int err;
printk(KERN_INFO "exFAT: Core Version %s\n", EXFAT_VERSION);
err = FsInit();
if (err) {
if (err == FFS_MEMORYERR)
return -ENOMEM;
else
return -EIO;
}
err = exfat_init_inodecache();
if (err)
goto out;
err = register_filesystem(&exfat_fs_type);
if (err)
goto out;
return 0;
out:
FsShutdown();
return err;
}
这里需要注意的数据结构如下:
static struct file_system_type exfat_fs_type = {
.owner = THIS_MODULE,
.name = "exfat",
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
.get_sb = exfat_get_sb,
#else
.mount = exfat_fs_mount,//根据目前的kernel版本,我们要使用这个函数probe文件系统(mount命令加载exfat时会使用调用到这个最终实际加载的文件系统函数)
#endif
#if EXFAT_CONFIG_KERNEL_DEBUG
.kill_sb = exfat_debug_kill_sb,
#else
.kill_sb = kill_block_super,
#endif
.fs_flags = FS_REQUIRES_DEV,
};
这个数据结构中
.name = "exfat",-------------标示新添加的文件系统名字,比如ext4,ext3......
.mount = exfat_fs_mount,------------这个函数会注册到文件系统中,在mount时调用加载,后续详细介绍。
上一章强调了exfat_fs_mount在linux mount的时候会调用到,本章节将详细描述这个函数的执行过程。
在安装exFAT(mount)的时候,存放exFAT文件系统的磁盘分区上的大部分数据结构的信息都会被拷贝到RAM(操作系统内存)中,从而使得内核避免了许多后续的操作,变得简单。由于exFAT磁盘数据结构都保存在exFAT磁盘分区的块中,所以当需要经常更新一些数据结构时,内核会利用页高速缓存来实现。
在实际mount一个文件系统的时候,exFAT文件系统依赖于虚拟文件系统的一个标准函数(mount_bdev)来实现文件系统信息的装载。
在我们的exfat-nofuse代码中,函数exfat_fs_mount调用mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super);来实现,在mount_bdev函数中通过exfat_fill_super函数来填充VFS中一个超级块对象,代码实现如下:
static struct dentry *exfat_fs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data) {
return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super);
}
现在我们来详细描述exfat_fill_super函数的功能:
1.分配exfat的super_block的私有数据(struct exfat_sb_info *sbi)需要用到的内存,并进行初始化
struct exfat_sb_info *sbi;
sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);
sb->s_fs_info = sbi;
mutex_init(&sbi->s_lock);
................
parse_options(data, silent, &debug, &sbi->options);/*解析mount exfat时传入的参数*/
2.初始化exfat的super_block的数据
sb->s_fs_info = sbi;
sb->s_flags |= MS_NODIRATIME;
sb->s_magic = EXFAT_SUPER_MAGIC;
sb->s_op = &exfat_sops;
sb->s_d_op = &exfat_ci_dentry_ops;
这里需要注意exfat_sops和exfat_ci_dentry_ops的实现内容
const struct super_operations exfat_sops = {
.alloc_inode = exfat_alloc_inode,
.destroy_inode = exfat_destroy_inode,
.write_inode = exfat_write_inode,
.evict_inode = exfat_evict_inode,
.put_super = exfat_put_super,
.sync_fs = exfat_sync_fs,
.statfs = exfat_statfs,
.remount_fs = exfat_remount,
.show_options = exfat_show_options,
};
static const struct dentry_operations exfat_ci_dentry_ops = {
.d_revalidate = exfat_revalidate_ci,
.d_hash = exfat_d_hashi,
.d_compare = exfat_cmpi,
};
3.FsMountVol函数加载exfat分区的Volume Boot Record(VBR)数据以及exfat特定分区数据,然后初始化exfat的super_block数据以及super_block的私有数据以及exfat文件系统必要的数据(后面专门一章再详细描述这个函数的实现)
4.exfat_hash_init函数初始化inode的hash table
5.在exfat文件系统中做codepage的初始化
6.创建exfat的root inode以及初始化,并把root inode挂载到hash table
注意exfat root inode的初始化
inode->i_op = &exfat_dir_inode_operations;
inode->i_fop = &exfat_dir_operations;
const struct inode_operations exfat_dir_inode_operations = {
.create = exfat_create,
.lookup = exfat_lookup,
.unlink = exfat_unlink,
.symlink = exfat_symlink,
.mkdir = exfat_mkdir,
.rmdir = exfat_rmdir,
.rename = exfat_rename,
.setattr = exfat_setattr,
.getattr = exfat_getattr,
#ifdef CONFIG_EXFAT_VIRTUAL_XATTR
.setxattr = exfat_setxattr,
.getxattr = exfat_getxattr,
.listxattr = exfat_listxattr,
.removexattr = exfat_removexattr,
#endif
};
const struct file_operations exfat_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = exfat_readdir,
.unlocked_ioctl = exfat_generic_ioctl,
.fsync = exfat_file_fsync,
};
7. 通过root inode创建root dentry
8. 完成
code如下:
static int exfat_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *root_inode = NULL;
struct exfat_sb_info *sbi;
int debug, ret;
long error;
char buf[50];
exfat_mnt_msg(sb, 1, 0, "trying to mount...");
/*
* GFP_KERNEL is ok here, because while we do hold the
* supeblock lock, memory pressure can't call back into
* the filesystem, since we're only just about to mount
* it and have no inodes etc active!
*/
sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);/*分配exfat私有的super_block的数据需要用到的内存*/
if (!sbi) {
exfat_mnt_msg(sb, 1, 0, "failed to mount! (ENOMEM)");
return -ENOMEM;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
mutex_init(&sbi->s_lock);
#endif
sb->s_fs_info = sbi;
sb->s_flags |= MS_NODIRATIME;
sb->s_magic = EXFAT_SUPER_MAGIC;
sb->s_op = &exfat_sops;
error = parse_options(data, silent, &debug, &sbi->options);/*解析mount exfat时传入的参数*/
if (error)
goto out_fail;
setup_dops(sb);
error = -EIO;
sb_min_blocksize(sb, 512);
sb->s_maxbytes = 0x7fffffffffffffffLL; /* maximum file size */
ret = FsMountVol(sb);//wangxf14_study
if (ret) {
if (!silent)
printk(KERN_ERR "[EXFAT] FsMountVol failed\n");
goto out_fail;
}
/* set up enough so that it can read an inode */
exfat_hash_init(sb);
/*
* The low byte of FAT's first entry must have same value with
* media-field. But in real world, too many devices is
* writing wrong value. So, removed that validity check.
*
* if (FAT_FIRST_ENT(sb, media) != first)
*/
/* codepage is not meaningful in exfat */
error = -EINVAL;
sprintf(buf, "cp%d", sbi->options.codepage);
sbi->nls_disk = load_nls(buf);
if (!sbi->nls_disk) {
printk(KERN_ERR "[EXFAT] Codepage %s not found\n", buf);
goto out_fail2;
}
sbi->nls_io = load_nls(sbi->options.iocharset);
if (!sbi->nls_io) {
printk(KERN_ERR "[EXFAT] IO charset %s not found\n",
sbi->options.iocharset);
goto out_fail2;
}
error = -ENOMEM;
root_inode = new_inode(sb);/*创建一个inode节点,这个函数就是在fs/inode.c中的new_inode函数*/
if (!root_inode)
goto out_fail2;
root_inode->i_ino = EXFAT_ROOT_INO;
root_inode->i_version = 1;
error = exfat_read_root(root_inode); //wangxf14_study
if (error < 0)
goto out_fail2;
error = -ENOMEM;
exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos);
insert_inode_hash(root_inode);/*将这个新的inode内存节点挂在hashtable中,这个函数在fs/inode.c中的insert_inode_hash函数*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
sb->s_root = d_make_root(root_inode);
#else
sb->s_root = d_alloc_root(root_inode);
#endif
if (!sb->s_root) {
printk(KERN_ERR "[EXFAT] Getting the root inode failed\n");
goto out_fail2;
}
exfat_mnt_msg(sb, 1, 0, "mounted successfully!");
return 0;
out_fail2:
FsUmountVol(sb);
out_fail:
exfat_mnt_msg(sb, 1, 0, "failed to mount!");
if (root_inode)
iput(root_inode);
if (sbi->nls_io)
unload_nls(sbi->nls_io);
if (sbi->nls_disk)
unload_nls(sbi->nls_disk);
if (sbi->options.iocharset != exfat_default_iocharset)
kfree(sbi->options.iocharset);
sb->s_fs_info = NULL;
kfree(sbi);
return error;
}
exFAT文件系统2相关推荐
- ExFat文件系统DBR受损恢复案例
ExFat文件系统DBR受损恢复案例 ExFat文件系统也FAT32相类似,同时也结合着NTFS中的知识. 下面我们手工分析EXFat文件系统DBR受损手工分析案例 手工恢复受损的DBR需要计算一下参 ...
- linux内核 fat,微软宣布exFAT文件系统规范,希望被Linux内核接纳
对于那些经常需要在 Linux 和 Windows 10 之间切换工作的人们来说,作为 FAT32 继任者的 exFAT 文件系统,能够为用户带来更好的体验.近日,微软宣布了 exFAT 文件系统规范 ...
- Android5.1设备无法识别exFAT文件系统的64G TF卡问题
64G TF卡刚买回来的时候默认exFAT文件系统,在电脑端(XP和WIN7)可以识别,但在我们Android5.1S设备无法识别,采用guiformat工具格式化为FAT32文件系统后才可以正常识别 ...
- FAT和EXFAT文件系统
源:FAT和EXFAT文件系统 转载于:https://www.cnblogs.com/LittleTiger/p/8022450.html
- linux 下exfat分区,exFAT 文件系统指南
国庆假期,我拍了一些手机视频,打算存到新买的移动硬盘. 然后,就傻眼了.我的 Mac 电脑无法写入移动硬盘,因为移动硬盘的默认文件系统是 NTFS,Mac 不支持写入 NTFS. 虽然可以买一个软件解 ...
- exfat文件系统(一)
由于工作需要,开始研究exfat文件系统. 从网络上获取到exfat文件系统的介绍 http://www.ntfs.com/exfat-overview.htm 同时在csdn上找到一篇文章针对这个翻 ...
- Android 7.0支持exfat文件系统
网上看了一圈,关于Android移植exfat支持的文章大多停留在Android 4.x,Android 6.0或7.0以上的基本空缺,所以决定自己写一篇,本文实践环境是MTK的Android 7.0 ...
- Android 11.0 支持exFAT文件系统
Android 11.0 支持exFAT文件系统 U盘常见文件系统类型有FAT32.NTFS.exFAT, Android默认支持FAT32, 一般也有NTFS类型编译选项, 但是exFAT由于版权 ...
- EXFAT文件系统的数据恢复教程-李林峰-专题视频课程
EXFAT文件系统的数据恢复教程-5673人已学习 课程介绍 本套课程讲的是用winhex磁盘编辑软件,手工恢复EXFAT文件系统中的数据. 课程收益 学习EXFAT文件系统的 ...
最新文章
- Java 分布式 RPC 框架性能大比拼,Dubbo 排第几?
- 全面理解ERC721的实现机制
- python如何进行双色球预测最准确_【原创】python基于大数据现实双色球预测
- Walking Robot
- coco 语义分割_YOLACT++:目前最热门的实时实例分割开源库
- JAVA正则表达式4种常用功能 [转]
- 谈谈tmpdir与innodb_tmpdir的区别和用处
- 什么是机器学习?机器学习的工作原理是什么?
- js传参不是数字_js中函数传参方式
- 计算机硬盘图标闪烁,电脑本地磁盘图标显示异常如何解决
- 快捷方式和活动桌面小贴
- Android videoView闪屏
- IntelliJ配置jenkins服务的Crumb Data
- 如何在word文档里复选框里打勾?
- 公众号和视频号互相绑定带来的功能
- 千牛挂“虹(Rainbow)”,域和角色不胜数
- CCF基础P29练习题解
- 深入理解矩阵的特征值和特征向量
- 关于很狗的军训qwq
- 小红帽 oracle,linux 小红帽 一键安装ffmpeg
热门文章
- Linux征途——总结与扩展
- 青春亦不在,无法在挥霍
- 【华为机试真题 Python实现】免单统计
- LVS-NAT网络地址转换模式
- pycharm安装requests库一直报错
- 解放双手,Android开发应该尝试的UI自动化测试
- 通过 zerotier 访问所在局域网的其他设备
- Graph Neural Networks for Social Recommendation(GraphRec2019)阅读笔记
- 关于JDBC连接MySQL的时候出现警告:Establishing SSL connection without server‘s identity verification is not recom
- 使用NATS消息中间件实现云边协同