【Android】细数Linux和Android系统中的伪文件系统

文章目录

  • 前言
  • Linux伪文件系统
  • cgroupfs
    • Linux的cgroups
    • Android的cgroups
  • debugfs
  • functionfs(/dev/usb-ffs/adb)
    • functionfs 的引入
      • sysfs是什么
  • procfs(/proc)
  • pstore(/sys/fs/pstore)
  • selinuxfs(/sys/fs/selinux)
  • sysfs(/sys)
  • 参考

前言

做了好些年Android开发,你了解过Linux伪文件系统吗?
在 Linux 中,伪文件系统(Pseudo Filesystem)是一种特殊的文件系统,它不涉及具体的物理存储设备,而是提供了一种接口,允许用户和应用程序以文件和目录的形式访问内核和其他系统信息。这些文件和目录在运行时被内核动态地生成,因此被称为伪文件系统。
阅读本文,我们一起来学习Android中的伪文件系统的方方面面。

Linux伪文件系统

尽管不是严格意义上的Android 文件系统,但 Linux 内核中提供的其他三种值得注意的文件系统也在 Android 上被使用。

请注意术语“伪文件系统”, 这些文件系统没有一个会被存储到物理存储设备上去的,相反它们是直接由内核中的回调函数维护的。也就是说,当要访问其中的一个文件或目录时,某个对应的内核级处理函数就会被调用。

这也意味着,这些文件系统并不真正占用存储空间(在内核所用的内存中,用于存放对应的 inode 和目录数据结构的开销不算)。更进一步说,每次访问伪文件系统中的某个文件或目录都要去调用系统的回调函数,所以这些文件和目录反映出的总是最新的实时更新的数据。

由此可以推出,讨论(伪文件系统中) 文件的大小是没有意义的,这也就是为什么用“Is -l”命令看到的这些文件都是空的的原因。

注意,由于这些文件都是由内核代码(由整个内核,或者在某些情况下,由某些内核模块
导出的,所以根据内核版本的不同,这些文件有时也会有所不同,而且文件中的内容(特别是 sysfs 中文件的内容)也是和硬件紧密相关的。

大多数伪文件系统中的文件都是以只读权限创建的,因为其用途是提供实时的诊断信息,向用户态程序提供一种使之能够查看一些内核态中原本是不可访问的变量和结构的机制。

不过有些文件实际上是可写的,这提供了一种更有用的能力,使得我们在用户态中就能实时地对内核中的数据施加影响。

不像在某些基于注册表的系统中,修改配置需要对各种隐藏的而且通常是不公开文档的注册表键和值进行操作那样,对伪文件系统中文件进行的修改,会立即产生作用,而且还不需要系统重启。

cgroupfs

Linux的cgroups

Linux 内核提供了一种重要的资源控制机制,它就是 cgroups。

一个 cgroup 就是一个可容纳一个或多个线程的组容器 (container group),它能把组中的所有线程视为一个整体,统一进行操作和策略设置。

在 Linux 内核文档以中,提供了关于 groups 的相当详尽的文档。为了便于在用户态中能把各个线程放置到不同的组中,cgroups 通过伪文件系统把它们自己导出到用户态中,这使得只需对这些文件进行简单的“写”操作,就能把一个线程添加到某个组中。

Android的cgroups

尽管 cgroups 用途广泛,可以以各种不同方式使用,但是在 Android 中却是以一种非常受限的方式使用它的。

只用于 CPU 使用记时和线程调度,如图:
在这里插入图片描述

Bionic 在每个进程启动时,通过/acct 为其设置了CPU 使用记时器,因此它能应用到系统中所有的进程上。

/sys/fs/cgroup/memory 可以被 ActivityManager(通过 android.os.Process 及其JNI方法 setSwappiness)访问。

最后,是/dev/cpuctl 目录,尽管它位于/dev 目录下,但仍是个由 Android调度策略 (scheduling policy)安装的 cgroup 目录。

在/init 启动时,它会安装该目录并创建其下的各个子目录,即

  • dev/cpuctl/tasks 对应系统任务
  • /dev/cpuctl/apps/tasks 对应运行在前台的应用
  • /dev/cpuctl/apps/bg_non_interactive/tasks 对应运行在后台的应用。

并以此对各个组进行调度。

每个组都被分配到一个“共享”CPU 的数值,并被赋予了一个可以运行的时间上限。这样就能防止因有意或无意的错误操作,导致某个进程完全占据整个 CPU 运行时间的情况发生。

/dev/cpuctl的配置是在/init.rc 中完成的,下图是/init.rc脚本中安装cpuctl cgroups的部分代码:
在这里插入图片描述

debugfs

debugfs 文件系统是用于(输出)内核级的调试信息的。

驱动以及类似的子系统可以自由地把驱动的调试信息转储到这个文件系统中。和其他伪文件系统一样,如果文件系统已经被 mount了,大量的调试信息就能像读取其他文件那样被读取出来。

不过请注意,debugfs 没有必要一定要被 mount 到系统中,而且内核也可以被编译成不支持debugfs 的形式。如果内核支持 debugfs,它就可以用下面这行简单的命令行命令 (通常是在/init.hardware.rc中执行)mount 上来:

mount -t debugfs none /sys/kernel/debug

尽管理论上可以把它 mount 到任意一个 mount 点上,但是因为它实在是太有用了,所以通常都能在“/”目录中找到它的符号链接。

比如,在模拟器镜像中,就有一个“/d”符号链接指向 debugfs 的 mount 点。

debugfs 中的内容是完全由内核的版本以及内核中实现了哪些 debug 特性决定的。

下图给出的是在各个版本的Android 内核中常见的几个文件/目录,位于/sys/kernel/debug目录中:
在这里插入图片描述

functionfs(/dev/usb-ffs/adb)

在Android 系统中,USB 的功能经常会需要根据用户的选择 ,即是以

  • USB 调试、
  • 大容量存储介质
  • 还是以其他方式连接设备

用户的这一选择将通过 init动态地进行重新配置,它是由一个特定的“gadget”驱动进行控制的。

传统的驱动程序(Android L之前的内核版本)需要通过sysfs 导出它的重新配置参数。这一做法是它被认为非常臃肿,并需要改进的原因之一。

functionfs 的引入

在2010年某个时候,一个相对较新的特性被引入Linux 内核,由 Linux内核提供一个通用的文件系统,使驱动能够获取用户态空间中发出的对配置修改的请求。

这一文件系统可以被认为是对 sysfs 的一个补充,只不过设计后者的目的是向用户态输出一些内核中的变量和驱动信息,而前者的设计目的是从用户态获取输入。root 用户可以使用 mkdir(2)创建目录,这会引起内核创建相应的内核对象,这些对象可以在稍后由在用户态中发起的、对目录中的伪文件进行的 write(2)操作予以初始化。

在 Unix-like 操作系统中,系统调用 mkdir 是用于创建目录的。系统调用的编号(通常用括号中的数字表示,例如 mkdir(2))是指该系统调用在系统调用表中的编号。在这个上下文中,(2) 表示系统调用表中的编号,而不是 mkdir 函数本身的参数。

sysfs是什么

sysfs 是 Linux 内核中的一种虚拟文件系统,用于向用户空间提供有关内核、设备和驱动程序的信息。它通常被挂载到 /sys 目录下。

以下是 sysfs 的主要特点和用途:

  1. 提供内核参数和配置信息: /sys 目录下的文件和目录包含有关内核运行时参数、配置选项和其他内核信息的数据。

  2. 设备和驱动程序信息: sysfs 提供了有关系统上的设备和驱动程序的信息。例如,你可以在 /sys/class/sys/bus 下找到有关不同设备类别和总线的信息。

  3. 动态生成: sysfs 中的文件和目录是在运行时动态生成的,以反映系统的当前状态。这使得用户空间能够动态地获取有关系统状态的信息。

  4. 与用户空间的接口: 用户空间的应用程序和工具可以通过读写 /sys 下的文件来与内核进行通信和配置。这提供了一种方便的用户接口,用于访问和配置系统信息。

  5. 用于设备文件:/sys/class/sys/devices 下,你可以找到关于系统中设备的信息,这对于设备管理和识别非常有用。

在使用 sysfs 时,一些常见的目录结构包括:

  • /sys/class: 包含有关设备类别的信息,例如网络设备、块设备等。
  • /sys/devices: 包含有关系统中所有设备的信息。
  • /sys/bus: 包含有关总线的信息,如 USB 总线、PCI 总线等。
  • /sys/module: 包含有关内核模块的信息。

用户和开发者可以通过查看和操作 sysfs 中的文件来获取关于系统和设备的详细信息,这对于调试、配置和监控系统非常有用。

procfs(/proc)

procfs 文件系统名副其实,它提供了一个基于目录的观察系统中运行的进程的方式。这个想法最初是出现在 Plan 9 操作系统上的,随后 Linux 马上吸收并改造了它,使之能提供大量关于进程、线程以及其他全方位的系统诊断信息。

不论在/proc 中提供太多东西到底是不是件好事,这都不妨碍它成为一个极为重要的文件系统。许多 Linux 实用程序(如 top、netstat、lsof和ifconfig)以及许多 Android 工具(如 procrank、librank) 都把它作为诊断信息的来源,没有它就不能运行。Linux 在 pro(5)的手册页中记录了相当详细的相关信息,并保持它不断更新。

pstore(/sys/fs/pstore)

pstore机制是 Linux 的一个内核特性(在3.5版时引入),它允许内核把部分物理内存(RAM)单独划为 persistent store 区。它在需要应用抓取内核崩溃(panic)时的数据非常有用。

内核崩溃是指内核中出现了内存破坏的情况。由于这类情况发生之后可能会影响到文件系统的执行逻辑。所以,这时任何向文件系统写入数据的操作,都可能使情况进一步恶化,甚至导致文件系统也被破坏掉。

UNIX 系统通常会把内核崩溃时的数据转储到 swap 分区里去,但这也不能保证重启之后数据一定都还在。而且 Android 是没有 swap 分区的,因此,剩下的唯一靠谱的解决方案是专门为此留出一部分物理内存,即一个专用的内存区域persistent store,让内核把它崩溃时的数据,至少是 bare minimum转储到这里来。

随后内核自动执行一次热重启(也就是中间不切断电源的重启),这也就意味着物理内存中的信息不会在重启的过程中而丢失。在重启的过程中,内核会去检查 persistent store 区,看看里面是不是留有上一次系统运行遗留下来的数据。如果有的话,它就会通过/sys/fs/pstore,让我们能在用户态中读取到这些数据。

在较旧版本的Android 系统中,这一功能是利用了一个被称为“RAM console”的 Android特有的特性(也算是某种 Android 内核技巧)提供的。追溯它的实现代码,我们发现它还是位于/init.rc 中。这段代码会从/proc/apanic console 和/proc/apanic threads 中获取数据,并把它们写到/data/dontpanic 中(这一大圈绕的,简直就是“银河系漫游指南”)。随着 pstore 功能的到来,这一实现方式已经被放弃,转而使用/sys/fs/pstore。

selinuxfs(/sys/fs/selinux)

和debugfs 一样,SELinuxFS 传统上也是 mount 在/sys 下,但却不是 sysfs 文件系统的一部分。这个文件系统是专供 SELinux 使用的,其中存储了与安装策略 (installed policy) 相关的文件。

这个文件系统中最重要的文件是 policy 和伪文件 enable。

其中,policy 提供了加载(编译,可以使用的二进制可执行文件的格式)安全策略。

enable 则用来切换这些策略是否要被强制执行。

sysfs(/sys)

从重要性上说,它的重要性仅次于procfs。sysfs 是在 Linux 内核版本 2.6 中作为对 procfs 的补充而被引入的,为了能把/proc 里的东西整理得井井有条些,把与硬件和模块相关的配置文件移到一个单独的目录中去,并让目录的层次也更清晰些。
你会发现,/sys 是个“整洁的”目录,伪文件被分门别类地放在各自所属的子目录中的地方。/sys的子目录如图:

在这里插入图片描述

不同的设备之间硬件配置的差异非常大,所以各种不同设备中的 sysfs 里存放的文件间的差别也非常大。Android 框架之所以能够免于受到因不同厂商选用不同的五花八门的硬件而带来的麻烦,完全要感谢硬件抽象层(HAL,Hardware Abstraction Layer),它是由/system/lib/libhardware.so及其插件构成的,因为硬件抽象层把对不同特定文件的调用封装成了更为统一的 API。

参考

《最强Android书:架构大剖析》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/424589.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RFID标签是什么?该技术有哪些应用领域?

射频识别(RFID)技术利用电磁场,自动识别和跟踪附在物体上的标签,其中,近场通信(NFC)是一种基于短距离RFID高频技术的标准,支持13.56 MHz的频率。 NFC技术在现今的产品中应用广泛&am…

【心得】java从CC1链入门CC链个人笔记

来劲了,感觉离真正的CTF又近了一步。 本文仅从一个萌新的角度去谈,如有纰漏,纯属蒟蒻。 目录 CC链概念 CC链学习前置知识 CC1链 Version1 Version2 Version3 CC链概念 CC链 Commons Collections apache组织发布的开源库 里面主要对…

一文教你写出高效的软件测试用例!微信朋友圈动态发送为例

🔥 交流讨论:欢迎加入我们一起学习! 🔥 资源分享:耗时200小时精选的「软件测试」资料包 🔥 教程推荐:火遍全网的《软件测试》教程 📢欢迎点赞 👍 收藏 ⭐留言 &#x1…

如何制作自己的实景中国视频地图?

让每一个人都有自己的地图! 我们在《水经微图Web版1.5.0发布》一文中,提到了水经微图(简称“微图”)Web版新增了视频气泡的功能。 现在,我们为你分享一下如何基于此功能,制作一个属于自己的实景中国视频地…

浏览器无网

目录 1.运行网络诊断,确认原因 原因A.远程计算机或设备将不接受连接(该设备或资源(Web 代理)未设置为接受端口“7890”上的连接 原因B.DNS服务器未响应 场景A.其他的浏览器可以打开网页,自带的Edge却不行 方法A:关闭代理 Google自带翻译…

第10章-以太网交换机工作原理

1. 交换网络(概念一) 2. 以太网(概念二) 3. MAC地址(概念三) 4. 交换机 4.1. 定义: 4.2. 工作流程: 4.3. 交换机的MAC地址表生成 4.4. 数据帧的转发 1. 交换网络(…

动态权限有哪些

定位权限: ACCESS_FINE_LOCATION:精确位置ACCESS_COARSE_LOCATION:大致位置 相机权限: CAMERA:访问摄像头 存储权限: READ_EXTERNAL_STORAGE:读取外部存储WRITE_EXTERNAL_STORAGE:…

14、Kafka ------ kafka 核心API 之 流API(就是把一个主题的消息 导流 到另一个主题里面去)

目录 kafka 核心API 之 流APIKafka流API的作用:流API的核心API:使用流API编程的大致步骤如下:代码演示 流API 用法MessageStream 流API 代码演示消息从 test1主题 导流到 test2主题演示使用匿名内部类对消息进行处理Topology 拓扑结构 讲解 代…

文心一言 VS 讯飞星火 VS chatgpt (185)-- 算法导论14.1 2题

二、用go语言,对于图 14-1中的红黑树 T 和关键字 x.key 为35的结点x,说明执行 OS-RANK(T,x) 的过程。 文心一言: 在红黑树中,OS-RANK(T, x) 是一个操作,用于计算节点 x 在红黑树 T 中的秩。秩是一个节点的…

vscode连不上虚拟机,一直密码错误

最近在做毕设,但是vscode使用连接不上虚拟机,我以为是网络配置的问题,一顿查阅没找到原因。 后来查了一下ssh的日志,发现ssh有消息,但是也提示密码错误。 没找到密码配置格式什么的,经查看sshd配置文件发现…

搭建互联网医疗平台:构建智慧医院APP的开发指南

本文将从技术层面出发,为大家提供构建互联网医疗平台、打造智慧医院APP的详细开发指南。 一、确定需求与功能 在开始开发之前,首先需要明确智慧医院APP的需求与功能。这包括患者预约挂号、在线咨询、病历查看、医疗报告查询等功能。 二、选择合适的开发…

C++ STL之list的使用及模拟实现

文章目录 1. 介绍2. list类的使用2.1 list类对象的构造函数2.2 list类对象的容量操作2.3 list类对象的修改操作2.4 list类对象的访问及遍历操作 3. list类的模拟实现 1. 介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭…