内核达人

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2|回复: 0

umount秀到我了

[复制链接]

25

主题

25

帖子

83

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
83
发表于 7 天前 | 显示全部楼层 |阅读模式
哈喽,大家好,我就是那个不喜欢在大厂搬砖,不喜欢在研究院做研究,只喜欢创业做计算机底层课程的coder,子牙老师

前两天写了篇关于mount底层运行原理的文章【mount藏着的Linux内核的秘密】,感兴趣的可以看看。如果你想看懂本篇文章,推荐你看看。如果你已然知道,那就不用看

mount,最常用的用法就是把新增的硬盘挂载到某个目录中,方便后续操作。umount,相反操作,卸载

mount操作进入Linux内核后,做了很多事情,本质是把这些struct串起来:task_struct、nsproxy、mnt_namespace、mount、vfsmount、mountpoint、super_block、dentry、inode、file_system_type

umount做的就是断开它们之间的联系。有了这层认知,找到相关代码就算通过umount了

开整~

不太一样
mount操作,是同步完成的。而umount操作,是异步完成的,涉及到延迟清理。这个我是怎么知道的?单步调试Linux内核误打误撞碰上的。接下来我把这个过程重现给大家

想研究umount,理所当然的在相关代码处下断点
运行起来,看在这里断下来的调用栈
是不是很奇怪,没看到ksys_umount,于是我就追了下代码,在函数task_work_run中找到了答案
调用自实现文件系统注册的卸载函数,是执行task->task_works执行到的。task->task_works中存储的是延迟执行的任务,是在内核态返回用户态之前执行。

你是不是想问,为什么要把umount的部分工作放到task->task_works中延迟执行?我也没想明白,于是问了下ChatGPT,贴下答案
你是不是还想问:什么时候把umount的部分工作放入task->task_works的?执行umount的过程中放入的,核心代码在函数mntput_no_expire中
所以umount的工作分两个阶段完成:阶段一,进入内核,执行ksys_mount,执行完将任务放入task->task_works;阶段二,内核态返回用户态的时候,把阶段一加入的任务拿出来执行,进行最后的清理工作

kill_litter_super
看下代码,这个函数主要完成super_block、inode、dentry的回收
函数d_genocide会遍历到所有的dentry,flags加上DCACHE_GENOCIDE,引用计数-1
接下来调用函数kill_anon_super,这个函数的主要功能是回收虚拟设备号、关联的dentry、inode
看下generic_shutdown_super代码
前面不是没有做dentry的清理工作吗,在函数shrink_dcache_for_umount中做了
1620行,断开super_block与dentry的关系,调用do_one_tree清理dentry。回收dentry的核心函数是dentry_kill
函数dentry_kill中,会断开dentry与inode的关系,断开该dentry与其父dentry的关系,代码我就贴了,感兴趣的可以自己去看源码,很容易看懂

继续执行,函数evict_inodes是清理该super_block关联的所有inode,代码我就不贴了,核心函数是destroy_inode,执行到i_callback,完成内存回收
代码474行, 把这个超级块从全局 sb->s_type->fs_supers 链表里摘掉,彻底移除  

至此,只剩孤零零的super_block没有被清理,其他都清理干净了

清理super_block
代码接着走,执行到put_super
在put_super中,回收super_block
现在super_block、dentry、inode都清理完了,mount、vfsmount、mountpoint可以清理了

cleanup_mnt
看代码
1104行,delayed_free_vfsmnt回收mount的内存
那mount与task_struct、nsproxy、mnt_namespace之间的连接是何时断掉的呢?执行ksys_mount过程中

ksys_mount
看核心代码
do_umount中执行到函数umount_tree
1465行,与父mount脱离关系

1483行,与mnt_namepsace脱离关系

此mount与父mount、mnt_namespace断掉关系后,调用函数mntput_no_expire,将mnt的清理工作包装成异步任务放入task->task_works,完工!

至此,umount在Linux内核中的所有工作流程都清晰了!



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|内核达人

GMT+8, 2025-12-6 12:38 , Processed in 0.112660 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表