司马牛忧曰:“人皆有兄弟,我独亡。”子夏曰:“商闻之矣:死生有命,富贵在天。君子敬而无失,与人恭而有礼。四海之内,皆兄弟也。君子何患乎无兄弟也?” 《论语》:颜渊篇
百篇博客系列篇.本篇为:
v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一切皆是文件
本篇开始说文件系统,它是内核五大模块之一,甚至有Linux的设计哲学是"一切皆文件"的说法。所以其重要性不言而喻.搞不清楚文件系统,内核肯定是没整明白.文件系统相关概念巨多,后续将结合内核源码详细阐述,本篇先说清楚源头概念:文件。
文件系统相关篇为:
- v62.02 鸿蒙内核源码分析(文件概念) | 为什么说一切皆是文件
- v63.04 鸿蒙内核源码分析(文件系统) | 用图书管理说文件系统
- v64.06 鸿蒙内核源码分析(索引节点) | 谁是文件系统最重要的概念
- v65.05 鸿蒙内核源码分析(挂载目录) | 为何文件系统需要挂载
- v66.07 鸿蒙内核源码分析(根文件系统) | 先挂到
/
上的文件系统 - v67.03 鸿蒙内核源码分析(字符设备) | 字节为单位读写的设备
- v68.02 鸿蒙内核源码分析(VFS) | 文件系统和谐共处的基础
- v69.04 鸿蒙内核源码分析(文件句柄) | 你为什么叫句柄 ?
- v70.05 鸿蒙内核源码分析(管道文件) | 如何降低数据流动成本
什么是文件
- 不说清楚什么是文件就说不清楚文件系统,更说不清楚内核是如何管理和为什么要这么来管理文件的。
- 现代操作系统为解决信息能独立于进程之外被长期存储引入了文件,将文件抽象成一个宽泛的概念,把文档、目录(文件夹)、键盘、监视器、硬盘、可移动媒体设备、打印机、调制解调器、虚拟终端,还有进程间通信(
IPC
)和网络通信等输入/输出资源都看成文件来统一操作. - 因为它们都具有共同的读和写共性,一旦具有普适性,可以抽象出理想的模型,通过这个模型,设计工作就会变得简单而有序,API的设计可以化繁为简。用户可以使用通用的方式去访问任何资源,使他们被处理时均可统一使用字节流方式,而差异部分则由相应的中间件做好对底层的适配。
不准确但是形象的例子
Linux 系统把硬件设备映射成文件,例如将摄像头映射为 /dev/video,然后就可以使用基本的函数操作它。用 open() 函数连接设备,再用 read() 函数读取图像,最后用 write() 函数保存图像。
而在声卡设备中,read() 函数会变为录音功能,write() 函数变为播放功能。文件类型
从内核视角将文件分成七种类型:普通文件 (- regular file)
大家普遍理解的文件属于此类,(如:图片,视频,mp3,ppt,zip == ),这类文件也叫正则文件,当然是无处不在.
turing@ubuntu:/home/tools$ ls -hil total 12M 1083954 -rwxrwxr-x 1 turing turing 2.3M Feb 18 18:55 gn 1083803 -rw-r--r-- 1 root root 9.4M Nov 25 2020 hapsigntoolv2.jar 1083802 -rw-r--r-- 1 root root 58K Nov 25 2020 hmos_app_packing_tool.jar
目录文件(d,directory file)
就是目录或者说文件夹,能用cd
命令进入的。它同样无处不在
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ls -lhi total 68K 1202976 drwxr-xr-x 3 turing turing 4.0K Jun 21 02:38 applications 1173738 drwxr-xr-x 10 turing turing 4.0K Jun 21 02:38 base 1106153 drwxr-xr-x 3 turing turing 4.0K Jun 21 02:38 build
块设备文件(b,block device)
就是存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。属性为 [b] :block device
,通常在/dev
目录下能看到它.
turing@ubuntu:/dev$ ls -lhi total 0 210 brwxr-xr-x 2 root root 420 Jul 23 18:59 block 337 brwxr-xr-x 2 root root 80 Jul 23 18:05 bsg
字符设备(c,char device)
字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。通常在/dev
目录下能看到它
turing@ubuntu:/dev$ ls -lhi total 0 124 crw------- 1 root root 10, 175 Jul 23 18:05 agpgart 373 crw-r--r-- 1 root root 10, 235 Jul 23 18:05 autofs
套接字文件(s,socket)
这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信,最常在 /var/run目录中看到这种文件类型。
turing@ubuntu:/var/run$ ls -lhi 690 srw-rw-rw- 1 root root 0 Jul 23 18:05 snapd-snap.socket 689 srw-rw-rw- 1 root root 0 Jul 23 18:05 snapd.socket
管道文件(p,pipe)
管道文件主要用于进程间通讯。比如使用mkfifo
命令可以创建一个FIFO
文件,启用一个进程A
从FIFO
文件里读数据,启动进程B
往FIFO
里写数据,先进先出,随写随读。
turing@ubuntu:/var/run$ ls -lhi 269 prw------- 1 root root 0 Jul 23 18:05 initctl
符号链接文件(l,symbolic link)
这里说的链接指的是软链接,类似Windows下面的快捷方式。,这类文件非常多,尤其
/bin
,/usr/bin
目录下最多.
turing@ubuntu:/bin$ ls -lhi 143828 lrwxrwxrwx 1 root root 29 Jul 14 21:51 rmiregistry -> /etc/alternatives/rmiregistry 132128 lrwxrwxrwx 1 root root 4 Jul 14 19:10 rnano -> nano 132131 lrwxrwxrwx 1 root root 29 Jul 14 19:10 rrsync -> ../share/rsync/scripts/rrsync 132132 lrwxrwxrwx 1 root root 21 Jul 14 19:10 rsh -> /etc/alternatives/rsh
文件属性
文件属性,简单的说,有这么几种- 权限
- 所属者
- 所属组
1173738 drwxr-xr-- 10 turing turing 4.0K Jun 21 02:38 base
[ 0 ] [ 1 ] [ 2 ] [ 3 ][ 4 ] [ 5 ] [ 6 ] [ 7 ]
[vnode编号] [ 权限 ] [硬链接][拥有者][群组] [文件容量] [ 修改日期 ] [ 文件名]
[vnode编号] vnode
是文件系统非常重要的一个概念,后续有专门的篇幅结合源码详细说明,每个文件都有唯一的一个编号,跟身份证号一样,全国有100万人叫李伟
,大家沟通都是叫李伟
,不会喊身份证,并不影响沟通,但到了公安局就只认身份证,只要敢犯罪保准一逮一个准.所以视角不同,关注的点是不一样的。文件管理的机制是一模一样的,普通用户只需记住高清大片放在C:\xx\xx\xx\xx\xxx\xxx\xx.avi
下就可以了,不管埋的多深都能翻出来。根本不需要知道vnode.id
是多少。但到了内核层面,它操作的都是vnode.id
[权限] 对于多用户多群组的系统,就必须有权限来加持文件操作,该栏可以分成以下4个小组
d, rwx, r-x, r-x
- 第一个字符
d
单独成组,这个表示文件类型,这里表示是个目录文件(d,directory file) - 剩下的三个主要由[rwx]组成,r-read, w-write, x-execute, [-]表示占位符,即没权限。
- 第二组为『文件拥有者的权限』,
rwx
表示文件拥有者可读可写可执行 - 第三组为『同群组的权限』;
r-x
文件所属组可读可执行但不可写 - 第四组为『其他非本群组的权限』,
r--
其他人可读
- 第二组为『文件拥有者的权限』,
权限除了字母表示外还可以用数字表示
r=100=4, w=010=2, x=001=1, -=0 rwxr-xr-- 可表示为 111101100 = 754
chmod [-R] xxx
文件或目录 :改变文件拥有者
有两种方法可改变文件的权限
- 数字法 : chmod -R 777 ohos_config.json
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ls -hli 1103292 -rw-r--r-- 1 turing root 350 Jul 21 00:17 ohos_config.json turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ chmod -R 777 ohos_config.json turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ls -hli 1103292 -rwxrwxrwx 2 turing root 350 Jul 21 00:17 ohos_config.json
777
=(111)(111)(111)
=(rwx)(rwx)(rwx)
字母法 :
```
u +(加入) r
chmod g -(除去) w 文件或目录
o =(设定) x
a
(u)user (g)group (o)others (a)allchmod u=rwx,go=rx ohos_config.json 结果: rwxr-xr-x
chmod a+w ohos_config.json 结果: rwxrwxrwx
chmod u-r+wx ohos_config.json 结果: -wxrwxrwx
```
[链接] 一栏代表的是硬链接的数量,有硬链接就会有软链接,有什么区别呢。
先说清楚为什么会有链接 ? 原因是因为同一个文件往往需要被同一个用户或多个用户同时使用,好东西要懂得分享,好人一生平安,大片怎能独享。做个小实验看下二者的区别
#对ohos_config.json 创建硬链接和软链接
#创建硬链接命令 ln ohos_config.json hard_link
#创建软链接命令 ln -s ohos_config.json hard_link
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ls -hli
1103292 -rw-r--r-- 1 turing root 350 Jul 21 00:17 ohos_config.json
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ln ohos_config.json hard_link
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ln -s ohos_config.json soft_link
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ ls -hli
1103292 -rw-r--r-- 2 turing root 350 Jul 21 00:17 hard_link
1103292 -rw-r--r-- 2 turing root 350 Jul 21 00:17 ohos_config.json
1086100 lrwxrwxrwx 1 turing root 16 Jul 29 01:06 soft_link -> ohos_config.json
- 硬链接: 记录大片被分享的次数,
hard_link
和ohos_config.json
的vnode_id
都是1103292
,二者内容一模一样.但是和没创建之前的区别是[链接]数,也叫引用数,由1变成了2 。而新增加的这次引用数就是hard_link
导致的 - 软链接: 是单独创建了另一个文件,有独立的
vnode_id
,只是这个文件的内容指向了ohos_config.json
而已,这样做有什么好处呢? 举个例子就明白了。 - 某酒店301房住着一位美女,想进房间就需要有钥匙,只要去敲门就给你一把钥匙,离开了钥匙归还,硬链接就是301房间发出去的钥匙数量.那软链接是什么呢? 是旁边的302房间, 进入302房间里面只有一张纸条上面写着"去301房间敲门,你懂的"。明白了吗? 虽然绕了个湾,但换来的是非常灵活的操作,公安来了怎么办? 只需把纸条内容改成 "去404房间敲门。
404
房间在开民主生活会,啥问题也没有. - 在应用层是大量的软链接在被使用,比如 版本切换,升级软链接就非常的方便.
[拥有者]
chown
:改变文件拥有者
chown [-R]
账号名称 文件或目录
chown [-R]
账号名称:用户组名称 文件或目录
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ll
-rw-r--r-- 2 root root 350 Jul 21 00:17 ohos_config.json
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$sudo chown -R turing:turing ohos_config.json
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ll
-rw-r--r-- 2 turing turing 350 Jul 21 00:17 ohos_config.json
[群组]
chgrp [-R]
用户组名称 文件或目录
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ll
-rw-r--r-- 2 root root 350 Jul 21 00:17 ohos_config.json
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$sudo chgrp -R turing ohos_config.json
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ll
-rw-r--r-- 2 root turing 350 Jul 21 00:17 ohos_config.json
[修改日期]
用stat
命令可以查看一个文件的信息
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS$ stat ohos_config.json
File: ohos_config.json
Size: 350 Blocks: 8 IO Block: 4096 regular file
Device: 805h/2053d Inode: 1103292 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ turing) Gid: ( 0/ root)
Access: 2021-07-24 02:07:21.683190622 -0700
Modify: 2021-07-21 00:17:34.733766830 -0700
Change: 2021-07-29 01:20:14.314343117 -0700
Birth: -
mtime(modify time)
:修改时间是文件内容最后一次被修改的时间。比如:vim
操作后保存文件。ls -l
列出的就是这个时间atime(access time)
:访问时间是读一次文件的内容,这个时间就会更新。比如more
、cat
等命令。ls
、stat
命令不会修改atime
ctime(change time)
:状态改动时间,是该文件的vnode
节点最后一次被修改的时间,通过chmod
、chown
命令修改一次文件属性,这个时间就会更新
了解了文件后,再看文件系统.
文件系统
什么是文件系统? 看看维基百科的解释:
- 计算机的文件系统是一种存储和组织计算机数据的方法,它使得对其访问和查找变得容易,文件系统使用文件和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,用户使用文件系统来保存数据不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个文件的所属目录和文件名。在写入新数据之前,用户不必关心硬盘上的那个块地址没有被使用,硬盘上的存储空间管理(分配和释放)功能由文件系统自动完成,用户只需要记住数据被写入到了哪个文件中。
- 文件系统通常使用硬盘和光盘这样的存储设备,并维护文件在设备中的物理位置。但是,实际上文件系统也可能仅仅是一种访问资料的界面而已,实际的数据是通过网络协议(如NFS、SMB、9P等)提供的或者内存上,甚至可能根本没有对应的文件(如proc文件系统)。
- 严格地说,文件系统是一套实现了数据的存储、分级组织、访问和获取等操作的抽象数据类型。
简单地说,文件系统是操作系统中负责管理持久数据的子系统,基本数据单位是文件,它的目的是对磁盘上的文件进行组织管理,组织的方式不同,就会形成不同的文件系统。
计算机文件系统很像我们大学的智能图书管理系统,你去图书馆借书,只需在屏幕上选中要借的书本列表提交后会自动把书提取出来放到你的面前,你并不需要知道书本是如何被检测出来,它真实的摆放在几号馆的几号书架的第几排。每个大学都有一套独立的图书管理方式,有的按分类,有的按科目,有的按地域,有的按时间。 即便都按分类来的,分类的方法也会不一样,而且管理1万册很高效的方法却不一定对1000万册也同样高效,但衡量方法的好坏无非是看以下几个要素:
- 增删改查的速度要快,
- 存储空间要小,空间回收算法要好,
- 安全机制,什么人有什么权限对这本书执行什么操作。
- 各种操作记录,书的入库时间,最后的借阅时间,修改时间等等都要记录在案。
计算机的文件系统因为技术的更新,因为各个公司的利益保护等等诸多原因,肯定也是百花齐放的,跟计算机语言一样,绝大多数语言的发明只是为了解决某个实验室或者某个公司当下遇到的问题,很多压根没想那么远,标准和规范那都是后话,取决于你的市场规模和背后的金主。统一标准是好,但真的很难。世界语出现很多年了,但又有几个人去学。联合国存在也很多年了,就不听你,不交会费,你能有啥办法。经济基础决定上层建筑,这句话初中政治就反复讲,当初不理解,现在是彻底明白了,终究是要靠实力说话的。
所以不要去奇怪为什么会有这么多语言要学,这么多前端,后台框架要搞,互联网技术版图还处于群雄争霸时代,巨头林立,身处其中的码农都是绞肉机里的肉。而且这种分裂的趋势会愈演愈烈, PC
时代 Windows
一统天下, 手机时代 苹果,Android
楚汉相争,万物互联时代 鸿蒙,苹果,Fuchsia
很可能是三分天下。新生代不断崛起,老贵族不下牌桌。
文件系统按类型可分成以下四种:
- 磁盘文件系统 : 是一种设计用来利用数据存储设备来保存计算机文件的文件系统,最常用的数据存储设备是磁盘驱动器,可以直接或者间接地连接到计算机上。例如:
FAT
、exFAT
、NTFS
、HFS
、HFS+
、ext2
、ext3
、ext4
、ODS-5
、btrfs
、XFS
、UFS
、ZFS
。有些文件系统是行程文件系统(也有译作日志文件系统)或者追踪文件系统。 - 闪存文件系统 : 闪存文件系统是一种设计用来在闪存上储存文件的文件系统。随着移动设备的普及和闪存容量的增加,这类文件系统越来越流行。尽管磁盘文件系统也能在闪存上使用,但闪存文件系统是闪存设备的首选,理由如下:
- 擦除区块:闪存的区块在重新写入前必须先进行擦除。擦除区块会占用相当可观的时间。因此,在设备空闲的时候擦除未使用的区块有助于提高速度,而写入数据时也可以优先使用已经擦除的区块。
- 随机访问:由于在磁盘上寻址有很大的延迟,磁盘文件系统有针对寻址的优化,以尽量避免寻址。但闪存没有寻址延迟。
- 写入平衡(Wear levelling):闪存中经常写入的区块往往容易损坏。闪存文件系统的设计可以使数据均匀地写到整个设备。
日志文件系统具有闪存文件系统需要的特性,这类文件系统包括JFFS2
和YAFFS
。也有为了避免日志频繁写入而导致闪存寿命衰减的非日志文件系统,如exFAT
。
JFFS2
(全称: Journalling Flash File System Version2),是Redhat
公司开发的闪存文件系统,其前身是JFFS
,最早只支持NOR Flash
, 自2.6版以后开始支持NAND Flash
, 适合使用于嵌入式系统。YAFFS
(全称:Yet Another Flash File System)是由Aleph One
公司所发展出来的NAND Flash
嵌入式文件系统。 - 伪文件系统 : 启动时动态生成的文件系统,包含有关当前正在运行的内核的许多信息、配置和日志,由于它们放置在易失性存储器中,因此它们仅在运行时可用,而在关闭时消失。这些伪文件常挂载到以下目录:
sysfs (/sys)
,procfs (/proc)
,debugfs (/sys/kernel/debug)
,configfs (/sys/kernel/config)
,tracefs (/sys/kernel/tracing)
,tmppfs
(/dev/shm
,/run
,/sys/fs/cgroup
,/tmp/
,/var/volatile
,/run/user/
),devtmpfs
(/dev
)procfs
是 进程文件系统 (file system) 的缩写,用于通过内核访问进程信息。这个文件系统通常被挂载到/proc
目录。由于/proc
不是一个真正的文件系统,它也就不占用存储空间,只是占用有限的内存。tmpfs
(temporary file system) 是类Unix系统上暂存档存储空间的常见名称,通常以挂载文件系统方式实现,并将资料存储在易失性存储器而非永久存储设备中。所有在tmpfs上存储的资料在理论上都是暂时借放的,那也表示说,文件不会创建在硬盘上面。一旦重启,所有在tmpfs里面的资料都会消失不见。Sysfs
是Linux 2.6所提供的一种虚拟文件系统。这个文件系统不仅可以把设备(devices
)和驱动程序(drivers
)的信息从内核输出到用户空间,也可以用来对设备和驱动程序做设置。sysfs
的目的是把一些原本在procfs
中的,关于设备的部分,独立出来,以‘设备层次结构架构’(device tree)的形式呈现。devtmpfs
是在Linux
核心启动早期建立一个初步的/dev
,令一般启动程序不用等待udev
,缩短GNU/Linux
的开机时间。将设备也看成为文件,突出了Linux
文件系统的特点:一切皆文件或目录。
网络文件系统:
NFS
,(Network File System)是一种将远程主机上的分区(目录)经网络挂载到本地系统的一种机制,是一种分布式文件系统,力求客户端主机可以访问服务器端文件,并且其过程与访问本地存储时一样,它由Sun公司开发,于1984年发布。它的特点是将网络也看出了文件,再次体现一切皆文件的说法。
对于鸿蒙内核,JFFS2
,YAFFS
,tmpfs
,procfs
,FAT
,NTFS
,ZFS
将是后续章节的重点.
百篇博客分析.深挖内核地基
- 给鸿蒙内核源码加注释过程中,整理出以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切.确实有难度,自不量力,但已经出发,回头已是不可能的了。
- 与代码有bug需不断debug一样,文章和注解内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,v**.xx 代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。
按功能模块:
基础工具 | 加载运行 | 进程管理 | 编译构建 |
---|---|---|---|
双向链表 位图管理 用栈方式 定时器 原子操作 时间管理 |
ELF格式 ELF解析 静态链接 重定位 进程映像 |
进程管理 进程概念 Fork 特殊进程 进程回收 信号生产 信号消费 Shell编辑 Shell解析 |
编译环境 编译过程 环境脚本 构建工具 gn应用 忍者ninja |
进程通讯 | 内存管理 | 前因后果 | 任务管理 |
自旋锁 互斥锁 进程通讯 信号量 事件控制 消息队列 |
内存分配 内存管理 内存汇编 内存映射 内存规则 物理内存 |
总目录 调度故事 内存主奴 源码注释 源码结构 静态站点 |
时钟任务 任务调度 任务管理 调度队列 调度机制 线程概念 并发并行 CPU 系统调用 任务切换 |
文件系统 | 硬件架构 | ||
文件概念 文件系统 索引节点 挂载目录 根文件系统 字符设备 VFS 文件句柄 管道文件 |
汇编基础 汇编传参 工作模式 寄存器 异常接管 汇编汇总 中断切换 中断概念 中断管理 |
百万汉字注解.精读内核源码
四大码仓中文注解 . 定期同步官方代码
鸿蒙研究站( weharmonyos ) | 每天死磕一点点,原创不易,欢迎转载,请注明出处。若能支持点赞更好,感谢每一份支持。