SDcardFS文件系统浅析(四)- cat 过程
我们暂时先跳过源码,通过在sdcardfs文件系统中cat一个文件的过程,来了解sdcardfs的调用过程,在对其调用流程有个清晰理解后再去看代码,会事半工倍。
通过ftrace设置graph_function跟踪内核在cat 文件时sdcardfs的调用流程如下
sdcardfs cat过程
权限检查
//权限检查,检查打开文件read、write等权限,同时调用此函数权限必须有AID_SDCARD_RW sdcardfs_permission() { 6) 0.261 us | generic_permission(); //调用namei.c中的通用权限检查函数 6) 2.344 us | }
sdcardfs_d_revalidate
查内存中的各个dentry对象构成的结构是否仍然能够反映当前文件系统中的情况
6) 0.312 us | sdcardfs_hash_ci(); //计算散列值,该值用于将对象放置到dentry散列表中 6) 0.365 us | sdcardfs_cmp_ci(); //比较两个dentry对象的文件名 6) 0.469 us | sdcardfs_d_revalidate(); -------------------------------------------------------------------------------------------- sdcardfs_d_revalidate最终会调用底层文件系统的d_revalidate,它检查内存中的各个dentry对象构成的结构是否仍然 能够反应当前文件系统中的情况。一般用于网络文件系统,因为网络文件系统并不直接关联到内核/VFS,所有信息都 必须通过网络连接收集,可能由于文件系统在存储端的改变,致使某些dentry不再有效。该函数用于确保一致性,应 为sdcardfs是构建在底层文件系统之上,从架构上看和网络文件系统相似 -------------------------------------------------------------------------------------------- 6) | sdcardfs_d_revalidate() { 6) | 6) | dget_parent() { 6) 0.052 us | __rcu_read_lock(); 6) 0.104 us | __rcu_read_unlock(); 6) 1.250 us | } 6) | path_get() { 6) | mntget() { 6) 0.104 us | preempt_count_add(); 6) 0.052 us | preempt_count_sub(); 6) 2.188 us | } 6) 2.916 us | } 6) | path_get() { 6) | mntget() { 6) 0.053 us | preempt_count_add(); 6) 0.052 us | preempt_count_sub(); 6) 1.198 us | } 6) 1.980 us | } 6) | dget_parent() { 6) 0.052 us | __rcu_read_lock(); 6) 0.104 us | __rcu_read_unlock(); ------------------------------------------------------------------------------------------- 上面上一段通过sdcardfs的dentry来获得底层文件系统的dentry,最终调用底层文件系统的d_revalidate 对应源码如下 parent_dentry = dget_parent(dentry); //获得sdcardfs父dentry sdcardfs_get_lower_path(parent_dentry, &parent_lower_path);//通过sdcardfs父dentry获得底层文件系统文件 //真实父路径 sdcardfs_get_real_lower(dentry, &lower_path); parent_lower_dentry = parent_lower_path.dentry; //真实文件系统父dentry lower_dentry = lower_path.dentry; //真实文件的dentry,这里就是cat的文件 lower_cur_parent_dentry = dget_parent(lower_dentry); if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) { err = lower_dentry->d_op->d_revalidate(lower_dentry, flags); //最终调用真实文件系统d_revalidate if (err == 0) { d_drop(dentry); goto out; } } -------------------------------------------------------------------------------------------- 6) | igrab() { 6) 3.021 us | } 6) 0.677 us | iput(); 6) | dput() { 6) 1.302 us | } 6) | dput() { //减少dentry使用计数,下同 6) 1.250 us | } 6) | path_put() { 6) | dput() { 6) 0.052 us | __rcu_read_lock(); 6) 0.052 us | __rcu_read_unlock(); 6) 1.198 us | } 6) | mntput() { 6) | mntput_no_expire() { 6) 3.646 us | } 6) 4.271 us | } 6) 6.771 us | } ...............
普通权限检查
------------------------------------------权限检查------------------------------------------- 6) | sdcardfs_permission() { 6) 0.052 us | generic_permission(); 6) 0.989 us | }
sdcardfs_open
---------------------------------------调用sdcardfs_open------------------------------------ 6) | sdcardfs_open() { 6) | dget_parent() { //拿到父dentry 6) 0.104 us | __rcu_read_lock(); 6) 0.104 us | __rcu_read_unlock(); 6) 1.250 us | } 6) 0.104 us | check_caller_access_to_name(); ------------------------------------------------------------------------------------------- 权限检查,十分重要,sdcardfs是替代fuse对安卓进行权限管控,该函数就监控open时候的权限,根节点始终具有访问权限, 其他UID的程序始终要通过packages.list控制,下面是源码 ===================== 相关部分可以参考下面博客,虽然说的是fuse,但是sdcard同理只是实现方式不同 android sdcard 权限管理策略研究 https://blog.youkuaiyun.com/louyong0571/article/details/45046163 ===================== //check_caller_access_to_name 源码