当前位置:网站首页>initramfs详解----设备文件系统
initramfs详解----设备文件系统
2022-08-03 01:02:00 【巭犇】
initramfs的重要作用之一就是允许内核将保存根文件系统的存储设备的驱动不再编译进内核。本文我们就将硬盘驱动编译为模块,然后去识别硬盘设备。说道驱动,那么驱动一定是外部硬件设备的驱动,所以在介绍驱动之前,先介绍一下Linux对设备的管理,以及随之而产生的设备文件系统。
什么是devtmpfs
既然提到设备,而且Linux将设备也抽象为文件,这里就不得不讨论一下设备文件或者说设备节点。通常情况下,某些需要从用户空间访问的设备都会在文件系统中建立一个设备文件,作为用户空间访问设备的接口。得益于Linux中虚拟文件系统的设计,用户空间的程序可以像访问普通文件一样,使用标准的文件访问接口实现与设备的交互。
根据FHS的规定,设备文件存放在/dev目录下。在Linux系统的早期,设备文件是静态创建的,所有的设备节点是手动、事先创建的。笔者还记得在早期制作Linux发行版时,安装系统时,需要静态安装大量的设备文件,把所有可能的设备节点一并创建出来。但是,这样带来的一个问题就是,随着设备的种类越来越多,这个目录会越来越大,对于某一台具体的机器来说,dev目录下充斥着大量无用的设备文件,因为某些设备在某些机器上根本就不存在。而且,这种方法会逐渐耗尽设备号,虽然可以通过扩展设备号的位数来增加设备号,但终究不是长久之计。
鉴于静态创建设备文件的种种问题,开发人员开发了devfs。devfs虽然解决了按需创建设备节点的机制,但是还是有很多问题,比如设备文件的名称依然由驱动开发人员在代码中指定,而不能由系统管理员指定。因此,后来又出现了udev,使得设备命名策略、权限控制等都在用户空间完成。如此,设备文件不再是静态创建,而是由udev根据内核检测到的实际连接的设备,创建相应的设备文件。
对于动态创建设备文件,推荐在/dev目录下挂载一个基于内存的文件系统。基于内存的文件系统会完全驻留在RAM中,读写可以瞬间完成。除了性能优势之外,基于内存的文件系统的另外一个特点就是没有持久性,基于内存的文件系统中的数据在系统重新启动之后不会保留。这看起来可能不像是个积极因素,然而,对于动态创建设备节点这种情况来说,这实际上是一个优势。在系统关闭后,所有的设备节点无须保留,系统重启后,udev将根据内核检测到的实际设备创建设备文件。
Linux从2.6.18开始采用udev,/dev目录使用了基于内存的文件系统tmpfs管理设备文件。
2009年初,开发人员又提出了devtmpfs,并在同年年底被Linux2.6.32正式收录。内核引导时,devtmpfs将所有注册的设备在devtmpfs中建立相应的设备文件,一旦进入用户空间,在启动udev前,就可以将devtmpfs挂载到/dev目录下。也就是说,在启动udev前,devtmpfs中已经建立了初步的设备文件,一般启动程序不必再等待udev建立设备节点,甚至在某些嵌入式系统上,不再需要udev创建设备节点,因为这个基本的/dev已经足够,从而缩短了系统的启动时间。同rootfs类似,devtmpfs也不是新设计的文件系统,如果内核配置支持tmpfs,那么其就是tmpfs;否则,devtmpfs就是ramfs,只不过换了一个名字而已。
/dev目录下保存了设备文件的名称
devfs解决/dev目录下设备文件号耗尽问题,但是设备文件的名称由驱动开发人员设置
udev实现了由内核自动检测到实际到设备,自动创建设备文件
devtmpfs内核引导时,devtmpfs将所有注册的设备在devtmpfs中建立相应的设备文件,一旦进入用户空间,在启动udev前,就可以将devtmpfs挂载到/dev目录下
[[email protected]_node02 ~]# cat /etc/mtab
...
devtmpfs /dev devtmpfs rw,nosuid,size=483816k,nr_inodes=120954,mode=755 0 0
...
测试devtmpfs
编译内核支持devtmpfs,并将内核与前面准备好的initramfs复制到虚拟机的目标系统上,然后重启进入操作系统。使用ls列出操作系统/dev下的设备文件
根据图可见,/dev目录下包含一个设备节点console。但是我们的initramfs中并没有包含这个设备节点,那么这个设备节点是谁创建的呢?大家一定还记得我们前面讨论过的内置的initramfs吧?没错,这个console就是由内置的initramfs创建的。
接下来我们使用下面的命令将ramfs挂载到/dev目录下。
mount -n -t ramfs none /dev
因为ramfs只是一个基于内存的文件系统,与设备无关,所以mount命令中的“device”参数可以使用任意字串描述。习惯上,对于这类没有具体设备的,一般使用字串“none”表示。但是mount命令不推荐这样使用,因为在某些情况下,某些提示很容易让用户费解,比如“mount:none already mounted”。这里我们暂时使用“none”,在最终系统中我们使用“udev”,表示该目录下的节点是由udev创建的。默认情况下,mount命令会在文件/etc/mtab中维护一份当前已挂载的文件系统列表,因为我们的initramfs中没有创建/etc/mtab文件,initramfs中也不需要,因此使用参数“-n”告诉mount不需维护这份列表。
挂载完成后,我们查看/dev下的设备文件。情况非常糟糕,/dev下挂载了一个空的ramfs文件系统,原有的console设备节点也被覆盖了,如上图所示。
接下来我们使用下面的命令将devtmpfs挂载到/dev目录下:
mount -n -t devtmpfs none /dev
挂载完成后,我们再次查看/dev下的设备文件。可以看到,devtmpfs下面已经建立了若干设备节点,如上图所示。
既然devtmpfs有这么多的好处,/dev目录当然要使用devtmpfs文件系统了。因此,按照下面的脚本修改initramfs中的init文件:
[[email protected]_node02 initramfs]# cat init
#!/bin/bash
echo "Hello Michael"
export PATH=/bin:/usr/bin:/usr/sbin
mount -n -t devtmpfs udev /dev
exec /bin/bash
边栏推荐
猜你喜欢
德邦科技通过注册:年营收5.8亿 国家集成电路基金为大股东
7.31
在表格数据上,为什么基于树的模型仍然优于深度学习?
图文详细解决IDEA使用Debug模式启动项目一直转圈圈跑起不来(亲测可以)
.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)
Wireshark data capture and analysis of the transport layer protocol (TCP protocol)
【飞控开发高级教程1】疯壳·开源编队无人机-飞控整机代码走读、编译与烧写
HCIP第十二天_二层MPLS实验
如何正确地配置入口文件?
麒麟信安邀您抢先看 | openEuler 志高远,开源汇智创未来-开放原子全球开源峰会欧拉分论坛最详细议程出炉
随机推荐
全栈---JSONP
pytest:如何调用 pytest
vue3的keepAlive缓存组件
文树勋率长沙市人大常委会主任会议成员莅临麒麟信安调研数字经济发展情况
Wireshark data capture and analysis of the transport layer protocol (TCP protocol)
暴力递归到动态规划 08(小马走象棋)
PHICOMM(斐讯)N1盒子 - Armbian5.77(Debian 9)基本配置
NVM和NRM
【SQL】—数据库操作、表操作
【遥控器开发基础教程5】疯壳·开源编队无人机-SPI(2.4G 双机通信)
.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)
接口流量突增,如何做好性能优化?
ASP.NET网络版进销存管理系统源码【源码免费分享】
Oracle 暴跌,倒下了!
优秀的 Verilog/FPGA开源项目总结及交流群
30岁测试开发年薪不足80万,还要被面试官diss混得太差?
全栈---Proxy
visual studio 2012 为啥这么优秀
自己做的选择
.NET in-depth analysis of the LINQ framework (four: IQueryable, IQueryProvider interface details)