SDcardFS文件系统浅析(四)- cat 过程

SDcardFS文件系统浅析(四)- cat 过程

我们暂时先跳过源码,通过在sdcardfs文件系统中cat一个文件的过程,来了解sdcardfs的调用过程,在对其调用流程有个清晰理解后再去看代码,会事半工倍。

通过ftrace设置graph_function跟踪内核在cat 文件时sdcardfs的调用流程如下

sdcardfs cat过程

  1. 权限检查

    //权限检查,检查打开文件read、write等权限,同时调用此函数权限必须有AID_SDCARD_RW
                        sdcardfs_permission() { 
    6)   0.261 us    |    generic_permission(); //调用namei.c中的通用权限检查函数
    6)   2.344 us    |  }

  2. 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    |    }
                        ...............
  3. 普通权限检查

    ------------------------------------------权限检查-------------------------------------------
    6)               |  sdcardfs_permission() {
    6)   0.052 us    |    generic_permission();
    6)   0.989 us    |  }

  4. 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.csdn.net/louyong0571/article/details/45046163
    =====================
    
    //check_caller_access_to_name 源码
    
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
docker-compose 是 Docker 官方的一个用于定义和运行容器化应用的工具。它使用 YAML 文件来配置应用的服务、网络和卷等方面的设置。 当使用 docker-compose 部署 MySQL 时,可能会遇到无法访问 MySQL 的问题。出现这种情况一般有以下几个可能的原因: 1. 网络配置问题:docker-compose 在默认情况下会创建一个默认的网络,并将所有定义的服务连接到该网络。如果服务的网络配置不正确,可能导致无法访问 MySQL。可以通过检查网络配置或创建自定义网络来解决此问题。 2. 端口映射问题:MySQL 默认使用 3306 端口进行通信,但是在容器内部的端口与宿主机上的端口之间可能存在映射问题。可以通过检查端口映射配置或使用容器的 IP 地址来解决此问题。 3. 认证问题:MySQL 服务通常需要进行身份验证才能访问。在 docker-compose 文件中,可以通过设置环境变量来指定 MySQL 的用户名和密码。如果未正确设置这些环境变量,可能导致无法访问 MySQL。可以检查环境变量配置或者在容器内部手动配置用户名和密码来解决此问题。 4. 容器启动顺序问题:如果在 docker-compose 文件中定义了多个服务,并且它们之间有依赖关系,那么容器启动的顺序可能会影响 MySQL 的访问。可以通过在容器之间添加依赖或者设置延迟启动来解决此问题。 总结起来,当 docker-compose 部署的 MySQL 无法访问时,通常是由于网络配置、端口映射、认证配置或容器启动顺序等问题造成的。通过检查这些配置,并进行适当的调整或修复,通常可以解决无法访问 MySQL 的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值