内核简介
在谈驱动之前,我们需要先谈内核。
内核,是一个操作系统的核心。是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础,决定着整个操作系统的性能和稳定性。
下面是微内核和宏内核的简易对照图(图片来自于网络):
微内核: 不包括应用层IPC、文件系统功能、设备驱动模块。微内核具有动态扩展性强的优点。Windows操作系统、华为的鸿蒙操作系统就属于这类微内核架构。
宏内核: 宏内核架构是将应用层IPC、文件系统功能、设备驱动模块都编译成一个整体。
- 优点:执行效率高
- 缺点:一旦我们想修改或增加内核某个功能时(如增加设备驱动程序)都需要重新编译一遍内核。
Linux操作系统正是采用了宏内核结构,但是它也区分内核空间和用户空间。
所以,我们得先有内核源码。然后编译内核,才能编译出驱动程序。
关于内核源码,我们有两种方式获取:
- 直接下载所需版本的kernel,国内个版本的下载地址:http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/。
- 如果是有ARM开发板,下载相应的SDK,SDK内就包含kernel。
内核源码目录和编译
文件夹 | 作用 |
---|---|
arch | 这个文件夹包含了一个Kconfig文件,用于设置这个目录里的源代码编译所需的一系列设定。支持的处理器架构都在它相应的文件夹中,如arm64、x86、riscv等。/boot:内核需要的特定平台代码/boot/dts:设备树文件/configs:存放专用配置文件/include:特定体系的头文件/lib:通用函数在特定体系结构的文件/mm:特定体系结构的内存管理文件 |
block | 块设备,是一些linux存储体系中关于块设备管理的代码,譬如说SD卡、iNand、Nand、硬盘等都是块设备。 |
crypto | 这个目录下放了一些各种常见的加密算法的源代码。 |
drivers | 驱动目录,里面分门别类的列出了linux内核支持的所有硬件设备的驱动源代码。 |
firmware | 固件目录,保存用于驱动第三方设备的固件。 |
Documentation | 存放相关说明文档,很多实用文档,包括驱动编写等 |
include | 存放内核所需、与平台无关的头文件,与平台相关的头文件已经被移动到 arch 平台的include 目录 |
kernel | 这个文件夹中的代码控制内核本身,在该文件夹下有个”power”文件夹,这里的代码可以使计算机重新启动、关机和挂起。 |
lib | 这个文件夹包含了内核需要引用的一系列内核库文件代码。 |
…… | 其余的文件夹作用请自行了解。 |
如果我们写自己的驱动程序,需要放到drivers目录下,具体的规则后面再细讲。
内核的编译,我们使用SDK中自带脚本进行编译,那个脚本中会配置好配置文件。
kernel menuconfig
menuconfig是Linux里面的一个软件,可以配置uboot,kernel,rootf,这里以kernel为例来配置。
在命令行进入内核根目录,执行以下命令进入menuconfig配置主界面
# 打开menuconfig配置界面
make ARCH=arm64 menuconfig
-
执行上述命令时,会读取内核目录下.config文件和/arch/arm64目录下的Kconfig文件
-
Kconfig文件用于决定配置界面会有哪些配置选项
-
.config文件用于决定每个配置项的值(Y、M、N)
-
当.config文件存在时,它会根据.config文件设定默认项.
-
若不存在.config文件,则根据各级Kconfig文件来设定菜单项
-
使用菜单配置完成并保存后,会将配置的结果保存到.config文件
Kconfig 文件
分布在各目录下的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文件相关的内核配置菜单。Kconfig是各种配置界面的源文件,内核的配置工具读取各个Kconfig文件,生成配置界面供开发人员配置内核。
- 文件位于:/kernel/arch/arm64/Kconfig
在内核配置make menuconfig(或xconfig等)时,从Kconfig中读出配置菜单,用户配置完后保存到.config(在顶层目录下生成)中。
.config 文件
在内核编译时,主Makefile调用这个.config,用于的内核编译配置。
- 文件位于 :kernel/.config
- 可以通过defconfig文件进行加载/生成
- 可以通过kernel menuconfig进行配置/生成
defconfig文件
一般由平台厂商提供,内核编译用做.config的参考。
- 文件位于:/kernel/arch/arm64/configs/xxx_defconfig
Makefile 文件
- 路径:kernel/Makefile
顶层Makefile,用于内核源码编译,建议好好阅读一下此文件。
- 路径:kernel/arch/arm64/Makefile
该文件包含在顶层makefile中,因此用户可以添加自己的特定于体系结构的标志和依赖项。
Linux驱动简介
Linux是文件型系统,所有硬件都会在对应的目录(/dev)下面用相应的文件表示。在文件系统的Linux下面,都有对应文件与键盘、鼠标和硬盘等实实在在的硬件设备关联,访问这些文件就可以访问实际硬件。按照读写存储数据的方式,我们可以把设备分为三大类:
**字符设备:**字符设备指能够像字节流串行顺序依次进行访问的设备,对他的读写是以字节为单位。
- 一个字节一个字节读写的设备
- 读取数据需要按照先后数据(顺序读取)
- 每个字符设备在/dev目录下对应一个设备文件,linux用户程序通过设备文件(或称 设备节点)来使用驱动程序操作字符设备。
- 常见的字符设备有鼠标、键盘、串口、SPI、I2C等
**块设备:**是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区。
- 数据以固定长度进行传输,比如512K
- 块设备能够随机访问,而字符设备则只能顺序访问。
- 块设备包括硬盘、磁盘、U盘和SD卡等
- 每个块设备在/dev目录下对应一个设备文件,linux用户程序可以通过设备文件(或称设备节点)来使用驱动程序操作块设备。
- 块设备可以容纳文件系统,所以一般都通过文件系统来访问,而不是/dev设备节点。
**网络设备:**不同于字符设备和块设备,不在/dev下以文件节点代表,而是通过单独的网络接口来代表。
- 网络接口没有像字符设备和块设备一样的设备号和/dev设备节点,只有接口名,如eth0,eth1
访问,而不是/dev设备节点。
**网络设备:**不同于字符设备和块设备,不在/dev下以文件节点代表,而是通过单独的网络接口来代表。
- 网络接口没有像字符设备和块设备一样的设备号和/dev设备节点,只有接口名,如eth0,eth1
- 对网络设备的访问只能通过socket操作,而不是open、closc、read、write