Linux设备驱动开发详解 基于最新的Linux4.0内核-第3章 Linux内核及内核编程

第3章 Linux内核及内核编程

3.1 Linux内核的发展与演变

1、UNIX操作系统
2、Minix操作系统
3、GNU计划
4、POSIX标准
5、互联网

3.2 Linux2.6后的内核特点

1、新的调度器
2、内核抢占
Linux 2.6 以后的内核仍然存在中断、软中断、自旋锁等原子上下文进程无法抢占执行的情况,这是 Linux 内核本身只提供软实时能力的原因。
3、改进的线程模型
4、虚拟内存的变化
5、文件系统
6、音频(ALSA取代OSS)
7、总线、设备和驱动模型
总线是三者联系起来的基础,通过一种总线类型,将设备和驱动联系起来。总线类型中的match() 函数用来匹配设备和驱动,当匹配操作完成之后就会执行驱动程序中的probe() 函数。
8、电源管理
9、联网和 IPSec
10、用户界面层
11、Linux 3.0 后 ARM 架构的变更
此外, ARM Linux 的代码在时钟、 DMA、 pinmux、计时器刻度等诸多方面都进行了优化和调整,也删除了 arch/arm/mach-xxx/include/mach 头文件目录,以至于 Linux 3.7 以后的内核可以支持多平台,即用同一份内核镜像运行于多家 SoC 公司的多个芯片,实现“一个Linux 可适用于所有的 ARM系统”。

3.3 Linux内核的组成

3.3.1 Linux内核源代码的目录结构

arch :包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386、 arm、arm64、 powerpc、 mips 等。 Linux 内核目前已经支持 30 种左右的体系结构。
在 arch目录下,存放的是各个平台以及各个平台的芯片对 Linux 内核进程调度、内存管理、中断等的支持,以及每个具体的 SoC 和电路板的板级支持代码。
block:块设备驱动程序 I/O 调度。
crypto:常用加密和散列算法(如 AES、 SHA 等),还有一些压缩和 CRC 校验算法。
documentation:内核各部分的通用解释和注释。
drivers :设备驱动程序,每个不同的驱动占用一个子目录,如 char、 block、 net、mtd、 i2c 等。
fs:所支持的各种文件系统,如 EXT、 FAT、 NTFS、 JFFS2 等。
include:头文件,与系统相关的头文件放置在 include/linux 子目录下。
init:内核初始化代码。著名的 start_kernel() 就位于 init/main.c 文件中。
ipc:进程间通信的代码。
kernel :内核最核心的部分,包括进程调度、定时器等,而和平台相关的一部分代码放在 arch//kernel 目录下。
lib:库文件代码。
mm:内存管理代码,和平台相关的一部分代码放在 arch/
/mm 目录下。
net:网络相关代码,实现各种常见的网络协议。
scripts:用于配置内核的脚本文件。
security:主要是一个 SELinux 的模块。
sound: ALSA、 OSS 音频设备的驱动核心代码和常用设备驱动。
usr:实现用于打包和压缩的 cpio 等。
include:内核 API 级别头文件。

3.3.2 Linux内核的组成部分

1、进程调度
控制系统中多个进程对CPU的访问,使得多个进程能在CPU中“并行”执行。
内核中使用tast_struct结构体描述进程,其中包含描述该进程内存资源、文件系统资源、文件资源、tty资源、信号处理等的指针。
Linux线程采用轻量级进程模型来实现,在用户空间通过 pthread_create() API 创建线程的时候,本质上内核只是创建了一个新的 task_struct,并将新 task_struct 的所有资源指针都指向创建它的那个 task_struct的资源指针。
绝大多数进程(以及进程中的多个线程)是由用户空间的应用创建的,当它们存在底层资源和硬件访问的需求时,会通过系统调用进入内核空间。
启动内核线程的函数为:pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
2、内存管理
作用:控制多个进程安全地共享主内存区域。
当 CPU 提供内存管理单元( MMU) 时, Linux 内存管理对于每个进程完成从虚拟内存到物理内存的转换。
3、虚拟文件系统
Linux 虚拟文件系统隐藏了各种硬件的具体细节,为所有设备提供了统一的接口。而且,它独立于各个具体的文件系统,是对各种文件系统的一个抽象。它为上层的应用程序提供了统一的 vfs_read()、vfs_write() 等接口,并调用具体底层文件系统或者设备驱动中实现的 file_operations 结构体的成员函数。
4、网络接口
提供了对各种网络标准的存取和各种网络硬件的支持。
分类:
网络协议:负责实现每一种可能的网络传输协议;
网络驱动程序:负责与硬件设备通信,每一种可能的硬件设备都有相应的设备驱动程序。
5、进程间通信
方法:信号量、共享内存、消息队列、管道、UNIX 域套接字等。
Android 内核则新增了 Binder 进程间通信方式。
5 个组成部分之间的依赖关系如下
进程调度与内存管理之间的关系:这两个子系统互相依赖。在多程序环境下,程序要运行,则必须为之创建进程,而创建进程的第一件事情,就是将程序和数据装入内存。
进程间通信与内存管理的关系:进程间通信子系统要依赖内存管理支持共享内存通信机制,这种机制允许两个进程除了拥有自己的私有空间之外,还可以存取共同的内存区域。
虚拟文件系统与网络接口之间的关系:虚拟文件系统利用网络接口支持网络文件系统( NFS),也利用内存管理支持 RAMDISK 设备。
内存管理与虚拟文件系统之间的关系:内存管理利用虚拟文件系统支持交换,交换进程定期由调度程序调度,这也是内存管理依赖于进程调度的原因。当一个进程存取的内存映射被换出时,内存管理向虚拟文件系统发出请求,同时,挂起当前正在运行的进程。

3.3.3 Linux内核空间与用户空间

高层程序往往不能访问低级功能,而必须以某种方式切换到低级模式。
ARM 处理器分为 7 种工作模式。
用户模式( usr) :大多数应用程序运行在用户模式下,当处理器运行在用户模式下时,某些被保护的系统资源是不能访问的。
快速中断模式( fiq):用于高速数据传输或通道处理。
外部中断模式( irq):用于通用的中断处理。
管理模式( svc):操作系统使用的保护模式。
数据访问中止模式( abt) :当数据或指令预取中止时进入该模式,可用于虚拟存储及存储保护。
系统模式( sys):运行具有特权的操作系统任务。
未定义指令中止模式( und) :当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。
ARM Linux 的系统调用实现原理是采用 swi 软中断从用户( usr)模式陷入管理模式( svc)。
Linux 只能通过系统调用和硬件中断完成从用户空间到内核空间的控制转移。

3.4 Linux内核的编译及加载

3.4.1 Linux内核的编译

配置内核命令:
make conf ig(基于文本的最为传统的配置界面,不推荐使用)
make menuconf ig(基于文本菜单的配置界面)
make xconf ig(要求 QT 被安装)
运行 make menuconfig 等时,配置工具首先分析与体系结构对应的 /arch/xxx/Kconfig 文件( xxx 即为传入的 ARCH参数), /arch/xxx/Kconfig 文件中除本身包含一些与体系结构相关的配置项和配置菜单以外,还通过 source 语句引入了一系列 Kconfig 文件,而这些 Kconfig又可能再次通过 source 引入下一层的 Kconfig。

3.4.2 Kconfig和Makefile

在 Linux 内核中增加程序需要完成以下 3 项工作。
1、将编写的源代码复制到 Linux 内核源代码的相应目录中。
2、在目录的 Kconfig 文件中增加关于新源代码对应项目的编译配置选项。
3、在目录的 Makefile 文件中增加对新源代码的编译条目。
1、实例引导: TTY_PRINTK 字符设备
2、Makefile
这里主要对内核源代码各级子目录中的 kbuild( 内核的编译系统) Makefile 进行简单介绍,这部分是内核模块或设备驱动开发者最常接触到的。
Makefile 的语法包括如下几个方面。
(1)目标定义
(2)多文件模块的定义
(3)目录层次的迭代
3、Kconfig
(1)配置选项
大多数内核配置选项都对应 Kconfig 中的一个配置选项( config):
● 每个配置选项都必须指定类型,类型定义后可以紧跟输入提示。
● 输入提示的一般格式
● 默认值的格式
● 依赖关系的格式
● 选择关系(也称为反向依赖关系)
● 数据范围的格式
● Kconfig 中的 expr(表达式)定义
(2)菜单结构
4、应用实例:在内核中新增驱动代码目录和子目录
为了使这个 Kconfig 能起作用,修改 arch/arm/Kconfig 文件,增加:
source “drivers/test/Kconf ig”
source 意味着引用新的 Kconfig 文件

3.4.3 Linux内核的引导

早前, bootloader 需要将启动信息以 ATAG 的形式封装,并且把 ATAG 的地址填充在 r2 寄存器中,机型号填充在 r1 寄存器中。
支持设备树( Device Tree)后, bootloader 则需要把 dtb 的地址放入 r2 寄存器中。
ARM Linux 也支持直接把 dtb 和 zImage 绑定在一起的模式(内核 ARM_APPENDED_DTB 选项“ Use appended device tree blob to zImage”), 这样 r2 寄存器就不再需要填充 dtb 地址了。

类似 zImage 的内核镜像实际上是由没有压缩的解压算法和被压缩的内核组成,所以在bootloader 跳入 zImage 以后,它自身的解压缩逻辑就把内核的镜像解压缩出来了。
用户空间的 init 程序常用的有 busybox init、 SysVinit、 systemd 等,它们的职责类似,把整个系统启动,最后形成一个进程树

3.5 Linux下的C编程特点

3.5.1 Linux编码风格
3.5.2 GNU与ANSIC

1、零长度和变量长度数组
2、case 范围
GNU C 支持 case x… y 这样的语法,区间 [x,y] 中的数都会满足这个 case 的条件
3、语句表达式
GNU C 把包含在括号中的复合语句看成是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方。
4、typeof 关键字
5、可变参数宏
6、标号元素
7、当前函数名
8、特殊属性声明
9、内建函数

3.5.3 do{}while(0)语句

为了保证宏定义的使用者能无编译错误地使用宏,它不对其使用者做任何假设

3.5.4 goto语句

3.6 工具链

3.7 实验室建设

3.8 串口工具

3.9 总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值