要进行嵌入式Linux产品的内核驱动开发,需要先了解内核目录的各文件夹下源码的作用,本文介绍Linux内核源码目录树下的各目录文件的作用。
目录树概览
解压Linux内核源码压缩包,将得到内核源码。内核源码很复杂,包含多级目录,形成一个庞大的树状结构,通常称为Linux源码目录树。进入源码所在目录,可以看到目录树顶层通常包含如下目录和文件:
arch/ crypto/ fs/
Kbuild MAINTAINERS README
security/ virt/ block/
Documentation/ include/
Kconfig Makefile REPORTING-BUGS
sound/ COPYING drivers/ init/
kernel/ mm/ samples/ tools/
CREDITS firmware/ ipc/ lib/
net/ scripts/ usr/
各个目录文件的简要说明如表1所列。
表1 Linux源码顶层目录简要说明
目录
内容
arch/
包含各体系结构特定的代码,如arm、x86、ia64、mips等linux 内核源代码情景分析,在每个体系结构目录下通常都有:
-boot 内核需要的特定平台代码
-kernel 体系结构特有的代码
-lib 通用函数在特定体系结构的实现
-math-emu 模拟FPU的代码,在ARM中,使用mach-xxx代替
-mm 特定体系结构的内存管理实现
-include 特定体系的头文件
block/
存放块设备相关代码
crypto/
存放加密、压缩、CRC校验等算法相关代码
Documentation/
存放相关说明文档,很多实用文档,包括驱动编写等
drivers/
存放Linux内核设备驱动程序源码。驱动源码在Linux内核源码中站了很大比例,常见外设几乎都有可参考源码,对驱动开发而言,该目录非常重要。该目录包含众多驱动,目录按照设备类别进行分类,如char、block、input、i2c、spi、pci、usb等
firmware/
存放处理器相关的一些特殊固件
fs/
存放所有文件系统代码,如fat、ext2、ext3、ext4、ubifs、nfs、sysfs等
include/
存放内核所需、与平台无关的头文件,与平台相关的头文件已经被移动到arch平台的include目录,如ARM的头文件目录
init/
包含内核初始化代码
ipc/
存放进程间通信代码
kernel/
包含Linux内核管理代码
lib/
库文件代码实现
mm/
存放内存管理代码
net/
存放网络相关代码
samples/
存放提供的一些内核编程范例,如kfifo;后者相关用户态编程范例,如hidraw
srcipts/
存放一些脚本文件,如menuconfig脚本
security/
存放系统安全性相关代码
sound
存放声音、声卡相关驱动
tools/
编译过程中一些主机必要工具
usr
cpio相关实现
virt/
内核虚拟机KVM
Linux内核源码数量很庞大,解压后大约好几百兆字节,要能在如此庞大的源码中找到有效代码,熟悉Linux源码目录树的结构是基本要求。每个目录所包含的代码量差异也很大,下面是从下载的一份源码解压后的统计结果,其中drivers目录几乎占了源码总量的一半,arch目录也差不多有1/4:
chenxibing@linux-compiler:~/linux-3.4.107$ du --max-depth=1 –h
2.0M ./lib
160K ./init
2.0M ./crypto
252M ./drivers
6.3M ./firmware
24M ./sound
232K ./ipc
5.3M ./kernel
3.7M ./tools
33M ./fs
192K ./virt
2.1M ./security
22M ./net
168K ./samples
119M ./arch
40K ./usr
2.4M ./mm
3.1M ./scripts
23M ./include
20M ./Documentation
888K ./block
519M .
快速确定主板关联代码
拿到一份源码和一块评估板,如何快速找到与这块板相关的源码,是很多研发人员都曾遇到过的问题。如果对内核源码结构有大概了解,要完成这些事情也不难,通常可按照基础代码、驱动代码和其它代码等方面来梳理。
1、基础代码
Linux移植通常分为体系结构级别移植、处理器级别移植和板级移植,各级别移植难易程度差异很大,工作量和调试方式也各不相同。一般的产品开发人员所进行的内核移植,通常都是板级移植,这是几个级别中最简单的。
从代码层面来看,通常把能让一个主板最小系统能运行的代码称为基础代码,这部分代码通常包含体系结构移植代码、处理器核心代码以及板级支持包的部分代码。理清了这部分代码,对于了解和掌握整个主板相关代码具有重要意义。
确定主板名称和默认配置文件。例如,对于EPC-28x工控板,其对应的默认内核配置文件为。通常来说,一个评估板的内核默认配置文件名称与评估板的名称相同或者有关联。确定了配置文件后,可用任何文本编辑器打开该配置文件,可以对配置的选项进行查看;或者进行make menuconfig配置,进入配置界面查看。
确定对应的主板文件。在ARM Linux移植代码中,每个评估板通常都有一个对应的主板文件,在目录下。大多数主板文件都以“board-”开头,采用“board-xxx.c”这样的文件名,例如;也有以“mach-”开头的,如。通常来说,一个评估板的主板文件名称与评估板的名称相同或者有关联。
如果遇到名称特征不是很明显,不能确定的情况,则建议打开默认配置文件,找到“CONFIG_MACH_XXX=y”这一行,确定主板对应的配置开关变量。然后打开文件,根据配置开关变量来确定主板文件。例如文件中有如下内容:
可以看到linux软件下载,这几个主板文件命名都既不是以“board-”开头,也不是以“mach-”开头,对于这种情况,通过Makefile文件来确定一下是比较好的做法。特别是对于主板开关变量对应非单一文件的,更需要查看Makefile来确定关联文件,否则有可能遗漏某个文件,造成代码阅读理解上的障碍。如CONFIG_MACH_ZYLONITE300对应着zylonite.c和zylonite _pxa300.c两个C文件。
2、驱动代码
Linux内核源码中接近一半的代码量是驱动,对某一个特定主板的系统而言,驱动也占据很大的比例,底层开发的很大一部分是驱动相关工作。掌握从众多驱动中找到正确的驱动源码文件,并根据产品的实际需求进行修改调整的方法,能有效促进产品开发的进度。
Linux内核源码树drivers目录很复杂,包含了各种外设的驱动。对嵌入式Linux开发而言,通常需要关注的目录如表2所列。
表2 常见驱动目录
目录
说明
drivers/gpio
系统GPIO子系统和驱动目录,包括处理器内部GPIO以及外扩GPIO驱动。遵循GPIO子系统的驱动,可通过/sys/class/gpio进行访问
drivers/hwmon
硬件监测相关驱动,如温度传感器、风扇监测等
drivers/i2c
I2C子系统驱动。各I2C控制器的驱动在i2c/busses目录下
drivers/input
输入子系统驱动目录
drivers/input/keyboard
非HID键盘驱动,如GPIO键盘、矩阵键盘等
drivers/input/touchscreen
触摸屏驱动,如处理器的触摸屏控制器驱动、外扩串行触摸屏控制器驱动、串口触摸屏控制器驱动等
drivers/leds
LED子系统和驱动,如GPIO驱动的LED。遵循LED子系统的驱动 ,可通过/sys/class/leds进行访问
drivers/mfd
多功能器件驱动。如果一个器件能做多种用途,通常需要借助MFD来完成。例如am3352的adc接口,可同时做adc和触摸屏控制器,所以需要实现MFD接口驱动
drivers/misc
杂项驱动。特别需要关注目录linux 下载,提供了i2c和spi接口的EEPROM驱动范例,所驱动的设备可通过/sys系统访问
drivers/mmc
sd/mmc卡驱动目录
drivers/mtd
MTD子系统和驱动,包括NAND、oneNAND等。注意,UBI的实现也在MTD中
drivers/mtd/nand
NAND FALSH的MTD驱动目录,包括NAND的基础驱动和控制器接口驱动
drivers/net
网络设备驱动,包括MAC、PHY、CAN、USB网卡、无线、PPP协议等
drivers/net/can
CAN设备驱动。Linux已经将CAN归类到网络中,采用socket_CAN接口
drivers/net/ethernet
所支持的MAC驱动。常见厂家的MAC驱动都能找到,如broadcom、davicom、marvell、micrel、smsc等厂家的MAC,处理器自带MAC的驱动也在该目录下
drivers/net/phy
PHY驱动,像marvell、micrel和smsc的一些PHY驱动
drivers/rtc
RTC子系统和RTC芯片驱动
drivers/spi
SPI子系统和SPI控制器驱动,含GPIO模拟SPI的驱动
drivers/tty
TTY驱动
drivers/tty/serial
串口驱动,包括8250串口以及各处理器内部串口驱动实现
drivers/uio
用户空间IO驱动
drivers/usb
USB驱动,包括USB HOST、Gadget、USB转串口以及OTG等支持
drivers/video
Video驱动,包括Framebuffer驱动、显示控制器驱动和背光驱动等。有的移植代码会将液晶屏配置通放在显卡控制器驱动目录下,例如omap2系列的LCD配置代码在目录下
drivers/video/backlight
背光控制驱动
drivers/video/logo
Linux内核启动LOGO图片目录
drivers/watchdog
看门狗驱动,包括软件看门狗和各种硬件看门狗驱动实现
熟悉各类驱动在源码树中的大概位置,能帮助在开发过程中快速进行驱动源码查找和定位。一个系统到底用了哪些代码,与系统本身外设相关,也与主板配置文件相关。
3、其它代码
还有一些代码是系统必须的代码,但在实际开发过程中通常很少需要进行关注,例如文件系统的实现代码、网络子系统的实现代码等。对这部分代码和主板的关联性,建议根据配置文件来确认。
如果想和教程一起实践学习linux 内核源代码情景分析,可以使用致远电子IoT-3960L工控板。
公众号介绍
致远电子官方微信公众号,一个汇聚500名工程师的研发测试分享平台,为您提供电子行业领先的产品技术与解决方案。