当前位置: 首页 > news >正文

root_fs文件系统结构分析和内核加载流程

目录

概述

1 根文件系统下目录介绍

2 文件系统内容分析

2.1 etc/inittab代码分析

2.2 /etc/init.d/rcS 代码分析

2.3 /etc/mdev.conf代码分析

2.3.1 功能概述

2.3.2 /etc/mdev.conf的详细代码

2.4 /etc/init.d/rcS的源代码文件

3 分析内核中加载root_fs的流程

3.1 调用入口一:vfs_caches_init

3.1.1 init_rootfs

3.1.2 init_mount_tree

3.1.2.1 vfs_kern_mount

3.1.2.2 配置root path

3.2 调用入口二: rest_init函数

3.2.1 函数调用关系

3.2.2 kernel_init函数


概述

本文主要详细分析了root_fs文件系统结构,对该文件目录下的每个类型的文件做了详细的介绍,并讲述各个文件的作用,其在内核中主要实现了什么功能,还介绍了内核加载root_fs的过程,详细跟踪了整个的加载流程,介绍每一个函数的调用关系。

1 根文件系统下目录介绍

嵌入式 Linux 中都需要构建根文件系统,构建根文件系统的规则在 FHS(Filesystem Hierarchy Standard)文档中,下面是根文件系统顶层目录。

目录名称内容
bin所有用户都可以使用的、基本的命令。
sbin基本的系统命令,它们用于启动系统、修复系统等。
usr共享、只读的程序和数据。
proc这是个空目录,常作为 proc 文件系统的挂载点。
dev该目录存放设备文件和其它特殊文件。
etc系统配置文件,包括启动文件。
lib存放共享库和可加载块(即驱动程序),共享库用于启动系统、运行根文件系统中的可执行程序。
boot引导加载程序使用的静态文件
home用户主目录,包括供服务账号锁使用的主目录,如 FTP
mnt临时挂接某个文件系统的挂接点,通常是空目录。也可以在里面创建空的子目 录。
opt给主机额外安装软件所摆放的目录
rootroot 用户的主目录
tmp存放临时文件,通常是空目录。
var存放可变的数据。

2 文件系统内容分析

默认的内核命令行上有 init=/linuxrc, 因此,在文件系统被挂载后,运行的第一个程序是根目录下的 linuxrc。 这是一个指向/bin/busybox 的链接,也就是说,系统起来后运行的第一个程序也就是 busybox 本身。

busybox首先将试图解析/etc/inittab 来获取进一步的初始化配置信息(参考 busybox 源代码 init/init.c 中)parse_inittab()函数。而事实上, root_qtopia 中并没有/etc/inittab 这个配置文件,根据 busybox 的逻辑,它将生成默认的配置 。

2.1 etc/inittab代码分析

查看busybox-1.13.3/init/init.c文件中parse_inittab()函数的源码:

代码第701行: new_init_action(SYSINIT, INIT_SCRIPT, ""),也就决定了接下去初始化的脚本是 INIT_SCRIPT 所定义的值。这个宏的默认值是"/etc/init.d/rcS".

#define INITTAB        "/etc/inittab"   /* inittab file location */
#ifndef INIT_SCRIPT
#define INIT_SCRIPT   "/etc/init.d/rcS" /* Default sysinit script. */
#endif

parse_inittab() 函数的源代码

2.2 /etc/init.d/rcS 代码分析

该文件的路径: /etc/init.d/rcS。详细分析代码如下:

代码第3~5行: 为启动环境设置必要的环境变量

代码第13行: 设置机器的名称

代码第15~18行:

挂载“虚拟”文件系统“/proc”和“/sys”,并且在/dev 目录上挂载一个 ramfs,相当于把原本 NAND Flash 上的只读的/dev 目录“覆盖”上一块可写的空的 SDRAM。

/sys 和挂载了 ramfs 的/dev 是正确创建设备节点的关键。对于 2.6.29 内核来说,已经没有了 devfs 的支持,创建设备节点只有通过两种办法由文件系统完成:

1) 制作文件系统镜像前用 mknod 手动创建好系统中所有的(包括可能有的)设备节点, 并把这些节点文件一起做进文件系统镜像中;

2)在文件系统初始化过程中,通过/sys 目录所输出的信息,在/dev 目录下动态的创建 系统中当前实际有的设备节点

代码第20~22行:

1)通过 mdev -s 在/dev 目录下建立必要的设备节点;

2)设置内核的 hotplug handler 为 mdev, 即当设备热插拔时,由 mdev 接收 来自内核的消息并作出相应的回应, 比如挂载 U 盘。

对于 mdev,需要注意的是,文件系统里存在/etc/mdev.conf 文件,它包含了 mdev 的配置信息。

代码第24~35行:用来挂载其他一些常用的文件系统,并在/var 目录下(同样是ramfs,可写的)新建必要的目录。

代码第36行:用来设定系统时间的,从硬件 RTC 中获取,要获取正确的时间,必须先设置好正确的时间(如何设置 RTC 见用户手册说明)。

代码第39~54行:启动一系列服务:

服务类型说明
syslog用于记录内核和应用程序 debug 信息
netd - inetd一个挂载启动各种网络相关服务的看守进程
httpd - http server进程
leds跑马灯看守进程

代码47~48行:配置网络设备(网卡): 设定本机回环地址为 127.0.0.1 2)运行网卡设置脚本/etc/init.d/ifconfig-eth0

查看/etc/init.d/ifconfig-eth0 文件的内容:

#!/bin/sh
​
echo -n Try to bring eth0 interface up......>/dev/ttySAC0
​
if [ -f /etc/eth0-setting ] ; thensource /etc/eth0-setting
​if grep -q "^/dev/root / nfs " /etc/mtab ; thenecho -n NFS root ... > /dev/ttySAC0elseifconfig eth0 downifconfig eth0 hw ether $MACifconfig eth0 $IP netmask $Mask uproute add default gw $Gatewayfi
​echo nameserver $DNS > /etc/resolv.conf
else
​if grep -q "^/dev/root / nfs " /etc/mtab ; thenecho -n NFS root ... > /dev/ttySAC0else/sbin/ifconfig eth0 192.168.1.230 netmask 255.255.255.0 upfi
fi
​
echo Done > /dev/ttySAC0
查看/etc/eth0-setting,源码如下:

2.3 /etc/mdev.conf代码分析

2.3.1 功能概述

/etc/mdev.conf文件查看源码:

1)原本串口驱动注册的设备名是 s3c2410_serial0, s3c2410_serial1 和s3c2410_serial2,而 mdev 则会在/dev 目录下对应生成 ttySAC0, ttySAC1 和 ttySAC2 以符合应用程序对于串口设备名称的习惯。

2) /dev/sdcard 和/dev/udisk 永远分别指向 SD 卡和U 盘的第一个分区。

3) 当 SD 卡或者 U 盘插入/拔出时,将这个消息传递给自定义的热插拔 handler, /bin/hotplug. 这个程序用于自动挂载可移动设备的,目前是 SD卡和 U 盘。它的逻辑很简单,将 SD 卡或者 U 盘的第一个分区作为 FAT/FAT32 挂载到/sdcard或者/udisk.

注意的问题:

当 SD 卡或者 U 盘上没有分区表或者第一个分区不是 FAT/FAT32 格式的时候,它就不能正常工作

2.3.2 /etc/mdev.conf的详细代码

# system all-writable devices
full        0:0 0666
null        0:0 0666
ptmx        0:0 0666
random      0:0 0666
tty     0:0 0666
zero        0:0 0666
​
# console devices
tty[0-9]*   0:5 0660
vc/[0-9]*   0:5 0660
​
# serial port devices
s3c2410_serial0 0:5 0666    =ttySAC0
s3c2410_serial1 0:5 0666    =ttySAC1
s3c2410_serial2 0:5 0666    =ttySAC2
s3c2410_serial3 0:5 0666    =ttySAC3
​
# loop devices 
loop[0-9]*  0:0 0660    =loop/
​
# i2c devices
i2c-0       0:0 0666    =i2c/0
i2c-1       0:0 0666    =i2c/1
​
# frame buffer devices
fb[0-9]     0:0 0666
​
# input devices
mice        0:0 0660    =input/
mouse.*     0:0 0660    =input/
event.*     0:0 0660    =input/
ts.*        0:0 0660    =input/
​
# rtc devices
rtc0        0:0 0644    >rtc
rtc[1-9]    0:0 0644
​
# misc devices
mmcblk0p1   0:0 0600    =sdcard */bin/hotplug.sh
sda1        0:0 0600    =udisk * /bin/hotplug.sh
 

2.4 /etc/init.d/rcS的源代码文件

#! /bin/sh
​
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
​
#
#   Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
/bin/hostname FriendlyARM
​
/bin/mount -n -t proc none /proc
/bin/mount -n -t sysfs none /sys
/bin/mount -n -t usbfs none /proc/bus/usb
/bin/mount -t ramfs none /dev
​
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
/bin/hotplug
# mounting file system specified in /etc/fstab
mkdir -p /dev/pts
mkdir -p /dev/shm
/bin/mount -n -t devpts none /dev/pts -o mode=0622
/bin/mount -n -t tmpfs tmpfs /dev/shm
/bin/mount -n -t ramfs none /tmp
/bin/mount -n -t ramfs none /var
mkdir -p /var/empty
mkdir -p /var/log
mkdir -p /var/lock
mkdir -p /var/run
mkdir -p /var/tmp
​
/sbin/hwclock -s
​
syslogd
/etc/rc.d/init.d/netd start
echo "                        " > /dev/tty1
echo "Starting networking..." > /dev/tty1
/etc/rc.d/init.d/leds start
echo "                        " > /dev/tty1
echo "Starting leds service..." > /dev/tty1
echo "                        "
​
/sbin/ifconfig lo 127.0.0.1
/etc/init.d/ifconfig-eth0
​
soundplayer /root/testsound.mp3&
/bin/rtm&
​
echo "                                  " > /dev/tty1
echo "Starting MiniTest, please waiting..." > /dev/tty1

3 分析内核中加载root_fs的流程

内核的启动时从start_kernel()开始的,在该函数中调用vfs_caches_init() 和rest_init函数。其具体函数调用关系如下图所示:

3.1 调用入口一:vfs_caches_init

文件地址: \init\main.c

vfs_caches_init()所在的文件地址: \fs\dcache.c

在vfs_caches_init()函数中调用mnt_init()函数

mnt_init()函数所在文件地址:\fs\namespace.c

在mnt_init()函数中调用 init_rootfs()init_mount_tree()初始化和挂载文件系统

函数调用关系如下:

3.1.1 init_rootfs

该函数所在的文件地址:fs\namespace.c

查看init_rootfs()的源码:

在init_rootfs函数中初始化RAM fs,函数调用关系:

3.1.2 init_mount_tree

在函数中匹配root_fs的类型;init_mount_tree()所在的文件地址:\fs\namespace.c

函数调用关系:

3.1.2.1 vfs_kern_mount

init_mount_tree()函数调用vfs_kern_mount()函数挂载文件系统

在vfs_kern_mount()函数中调用mount_fs(),函数中的调用关系

3.1.2.2 配置root path

在init_mount_tree()中还调用两个重要的函数:

代码3090行: set_fs_pwd()

代码3091行: set_fs_root()

3.2 调用入口二: rest_init函数

3.2.1 函数调用关系

函数调用关系:

函数rest_init中的细节如下:

代码394行: 该线程调用kernel_init,初始化root_fs其他的参数

3.2.2 kernel_init函数

函数调用关系:

kernel_init()的详细代码如下:

相关文章:

root_fs文件系统结构分析和内核加载流程

目录 概述 1 根文件系统下目录介绍 2 文件系统内容分析 2.1 etc/inittab代码分析 2.2 /etc/init.d/rcS 代码分析 2.3 /etc/mdev.conf代码分析 2.3.1 功能概述 2.3.2 /etc/mdev.conf的详细代码 2.4 /etc/init.d/rcS的源代码文件 3 分析内核中加载root_fs的流程 3.1 调…...

macOS系统配置RUST开发环境

打开rust语言官方网,然后点击马上开始: Rust 程序设计语言 配置RUST开发环境: 使用curl下载rust安装脚本: 复制到终端执行: curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs | sh 输入: y 选择默认安装,输入: 1...

Android 15全面解读:性能飙升、隐私守护与智能生活新纪元

1. 更强大的性能 Android 15 带来了一系列性能方面的改进,以确保您的设备在运行应用程序时能够更加流畅。通过对系统进行优化,Android 15 在响应速度和性能方面都有了显著的提升。 这些优化包括: 新一代处理器支持: Android 15 …...

Java项目:80 springboot师生健康信息管理系统

作者主页:源码空间codegym 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统的角色:管理员、宿管、学生 管理员管理宿管员,管理学生,修改密码,维护个人信息。 宿管员…...

云服务器配置 docker-spark

云服务器配置 docker-spark 1. 安装2. 启动3. 查看4. 验证5. 其他 1. 安装 我的服务器是腾讯云轻量应用服务器,2 核 2 G,已经内置了 docker, 配置大概如下: ubuntuVM-20-5-ubuntu --------------------- OS: Ubuntu 22.04 LTS x…...

Matlab之求直角坐标系下两直线的交点坐标

目的:在直角坐标系下,求两个直线的交点坐标 一、函数的参数说明 输入参数: PointA:直线A上的点坐标; AngleA:直线A的倾斜角,单位度; PointB:直线B上的点坐标&#xf…...

Python3:ModuleNotFoundError: No module named ‘elftools‘

问题背景 问题 ModuleNotFoundError: No module named ‘elftools’ 解决方法 pip3 install pyelftools 成功!!!...

【Vue】创建vue项目 npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED

在安装完vue后,一段时间后发现再次使用出错;感觉可能是使用了代理的原因,但是就算关闭了代理一样不行;最后重启大法解决。 此处记录解决时使用到的命令。 检查版本 node -v cnpm -v vue --version vue -V安装 npm install -g vu…...

5、Cocos Creator 动作系统

目录 1、动作系统 API 2、动作系统 API 3、缓动动作 4、参考 动作系统并不能取代动画系统,动作系统提供的是面向程序员的 API 接口,而动画系统则是提供在编辑器中来设计的。它们服务于不同的使用场景,动作系统比较适合来制作简单的形变和…...

web3 token 如何理解

"Web3 Token"是指建立在Web3技术堆栈上的数字令牌。为了更好地理解这个概念,让我们逐步解释: Web3:指的是下一代互联网(Web3.0),它是基于区块链技术的去中心化网络。Web3的核心理念是去中心化、安…...

unity pivot和center的区别

在Unity中,“pivot” 和 “center” 是两个在物体变换和编辑过程中经常提到的概念,它们表示物体的不同位置或者参考点。下面是它们的区别: Pivot(中心点): Pivot 是物体的旋转和缩放的参考点。在 Unity 中&…...

Python学习笔记-简单案例实现多进程与多线程

Python 的多进程与多线程是并发编程的两种重要方式,用于提高程序的执行效率。它们各自有不同的特点和适用场景。 多进程(Multiprocessing) 概念: 多进程是指操作系统中同时运行多个程序实例,每个实例称为一个进程。…...

python常用的语法

Python是一种高级、通用、解释型的编程语言,具有简洁、易于阅读和理解的语法。以下是Python中常用的语法: 变量定义和赋值: variable value输出内容: print("Hello, World!")条件判断: if condition:# 条件…...

【计算机网络】概述

📝本文介绍 本文为计算机网络的概述,会综合概述一下计算机网络 👋作者简介:一个正在积极探索的本科生 📱联系方式:943641266(QQ) 🚪Github地址:https://github.com/sankexilianhua &…...

【Flink connector】文件系统 SQL 连接器:实时写文件系统以及(kafka到hive)实战举例

文章目录 一. 滚动策略:sink后文件切分(暂不关注)1. 切分分区目录下的文件2. 小文件合并 二. 分区提交1. 分区提交触发器 (什么时候创建分区)1.1. 逻辑说明1.2. 举例说明 2. 分区时间提取器 (用于partition-time情况下partition commit策略)2…...

RpcContext :提供了在 RPC 调用过程中访问当前调用信息的方法

在 Dubbo 中,RpcContext 是一个上下文对象,它提供了在 RPC 调用过程中访问当前调用信息的方法。RpcContext.getClientAttachment() 方法用于获取客户端设置的附件(Attachment)信息。这些附件信息通常是在 RPC 调用发起方&#xff…...

机器学习 - 提高模型 (代码)

如果模型出现了 underfitting 问题,就得提高模型了。 Model improvement techniqueWhat does it do?Add more layersEach layer potentially increases the learning capabilities of the model with each layer being able to learn some kind of new pattern in…...

数值代数及方程数值解:预备知识——二进制及浮点数

文章目录 二进制IEEE浮点数 本篇文章的前置知识:数学分析 二进制 命题:二进制转化为十进制 二进制的数字表示为 ⋯ b 2 b 1 b 0 . b − 1 b − 2 ⋯ \cdots b_2b_1b_0.b_{-1}b_{-2}\cdots ⋯b2​b1​b0​.b−1​b−2​⋯这等价于十进制下的 ⋯ b 2 2 …...

新数字时代的启示:揭开Web3的秘密之路

在当今数字时代,随着区块链技术的不断发展,Web3作为下一代互联网的概念正逐渐引起人们的关注和探索。本文将深入探讨新数字时代的启示,揭开Web3的神秘之路,并探讨其在未来的发展前景。 1. Web3的定义与特点 Web3是对互联网未来发…...

算法——动态规划:01背包

原始01背包见下面这篇文章:http://t.csdnimg.cn/a1kCL 01背包的变种:. - 力扣(LeetCode) 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 简化一…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

【AI学习】三、AI算法中的向量

在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found"​, "n…...