第3章--Linux内核及内核编程

文章详细介绍了Linux内核的目录结构,包括架构相关的代码、驱动、文件系统等,并探讨了内核的组成部分,如进程调度、内存管理和虚拟文件系统。此外,还阐述了内核的编译过程,如配置和编译命令,以及内核如何通过BootLoader加载到系统中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、源代码目录结构

/arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录。
/block:块设备驱动程序I/O调度。
/crypto:常见加密和散列算法,以及一些压缩和CRC校验算法。
/documentation:内核各部分的通用解释和注释。
/drivers:设备驱动程序,每个不同的驱动占用一个子目录。
/fs:所支持的各种文件系统。
/include:内核API级别头文件。
/init:内核初始化代码。
/ipc:进程间通信的代码。
/kernel:内核最核心的部分,包括进程调度、定时器等。
/lib:库文件代码。
/mm:内存管理代码。
/net:网络相关代码,实现各种常见的网络协议。
/scripts:用于配置内核的脚本文件。
/sound:音频设备的驱动核心代码和常见设备驱动。
/usr:实现用于打包和压缩。

二、内核的组成部分

1. 进程调度

Linux的进程在几个状态间进行切换。(就绪、暂停、睡眠、执行等)
在设备驱动编程中,当请求的资源不能得到满足时,内核一般会调度其他进程执行,
并使本进程进入睡眠状态,直到他请求的资源被释放,才会被唤醒而进入就绪状态。
睡眠分为可中断的睡眠和不可中断的睡眠,两者的区别在于可中断的睡眠在收到信号的时候会醒。

2. 内存管理

一般而言,32位处理器的Linux的每个进程享有4GB的内存空间,0到3GB属于用户空间,3到4GB属于内核空间,内核空间对常规内存、I/O设备内存以及高端内存有不同的处理方式。
当然,内核空间和用户空间的具体界限是可以调整的,在内核配置选项Kernel Fearures -> Memory split下,可以设置界限为2GB或者3GB。

3. 虚拟文件系统

Linux虚拟文件系统隐藏了各种硬件的具体细节,为所有设备提供了统一的接口。
而且,他独立于各个具体的文件系统,是对各种文件系统的一个抽象。
他为上层的应用程序提供了统一的vfs_read()、vfs_write()等接口,并调用具体底层文件系统或者设备驱动中实现的file_operations结构体的成员函数。

4. 网络接口

网络接口提供了对各种网络标准的存取和各种网络硬件的支持。
在Linux中网络接口可分为网络协议和网络驱动程序,网络协议部分负责实现每一种可能的网络传输协议,网络设备驱动程序负责与硬件设备通信,每一种可能的硬件设备都有相应的设备驱动程序。

5. 进程间通信

进程间通信支持进程之间的通信,Linux支持进程间的多种通信机制,包括信号量、共享内存、消息队列、管道、UNIX域套接字等,这些机制可协助多个进程、多资源的互斥访问、进程间的同步和消息传递。

三、内核的编译

在编译内核时,需要先配置内核,使用以下命令:

make menuconfig

内核配置包含的条目相当多,arch/arm/configs/xxx_defconfig文件包含了许多电路板的默认配置。
只需要运行make ARCH=arm xxx_defconfig就可以为xxx开发版配置内核。
编译内核和模块的方法是:

make ARCH=arm zImage
make ARCH=arm modules

Linux内核的配置系统由以下3个部分组成。

  • Makefile:分布在Linux内核源代码中,定义Linux内核的编译规则。
  • Kconfig:配置文件,给用户提供配置选择的功能。
  • 配置工具:包括配置命令解释器和配置用户界面。

使用make config、make menuconfig等命令后,会生成一个.config配置文件,记录哪些部分被编译进内核、哪些部分被编译为内核模块。
运行make menuconfig时,配置工具首先分析与体系结构相应的/arch/xxx/Kconfig文件(xxx即为传入的ARCH参数),/arch/xxx/Kconfig文件中除本身包括一些与体系结构相关的配置项和配置菜单外,还通过source语句引入了一系列Kconfig文件,而这些Kconfig有可能再次通过source引入下一层的Kconfig,配置工具依据Kconfig包括的菜单和条目即可描绘出一个分层结构。

四、内核的加载

引导Linux系统的过程包括很多阶段,一般的SOC内嵌入了bootrom,上电时bootrom运行。对于CPU0而言,bootrom会去引导BootLoader,而其他CPU则判断自己是不是CPU0,进入WFI的状态等待CPU0来唤醒它。

CPU0引导BootLoader,BootLoader引导Linux内核,在内核启动阶段,CPU0会发中断唤醒CPU1,之后CPU0和CPU1都投入运行。CPU0导致用户空间的init程序被调用,init程序再派生其他进程。
CPU0和CPU1共担这些负载,进行负载均衡。
bootrom是各个SOC产家根据自身情况编写的,目前的SOC一般都具有从SD、eMMC、NAND、USB等介质启动的能力,这证明这些bootrom内部的代码具备读SD、NAND等能力。
早前,BootLoader需要把启动信息以ATAG的形式封装,并且把ATAG的地址填充在r2寄存器中,机型号填充在r1寄存器中。
在ARM Linux支持设备树(Device Tree)后,BootLoader则需要把dtb的地址放入r2寄存器中。
当然,ARM Linux也支持直接把dtb和zImage绑定在一起的模式(内核ARM_APPENDEN_DTB选项"Use appended device tree blob to zImage"),这样r2寄存器就不再需要填充dtb地址了。
类似zImage的内核镜像实际上是由没有压缩的解压算法和被压缩的内核组成,所以在BootLoader跳入zImage以后,他自身的解压缩逻辑就把内核的镜像解压缩出来了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值