完善 10.1 节. #8
105
Chapter10_Linux_Driver/10.1_概述.md
Normal file
105
Chapter10_Linux_Driver/10.1_概述.md
Normal file
@ -0,0 +1,105 @@
|
||||
# 10。1 概述
|
||||
|
||||
## 嵌入式系统的分类
|
||||
|
||||
SOC:通常内存较大,使用外部磁盘,大容量 Flash 或 EMMC,有 MMU,区分用户态和内核态,运行 Linux/Android/WinCE 等大型系统,应用程序与系统可分开编译,系统可动态安装程序,一般使用远程 GDB 和日志输出方式进行调试。开发分为 BSP、驱动、中间件、应用/UI 等。比如 Intel Atom 系列、ARM Cortex A 系列。
|
||||
|
||||
MCU:通常内存和 Flash 较小,无 MMU,不区分用户态和内核态,无系统或运行小型实时系统,应用程序与系统一起编译形成镜像进行烧录,通常采用 JTAG 等硬件调试器进行调试。开发不分家或分为系统、驱动、应用开发。比如 ARM Cortex M 系列、Atmel AVR 系列、TI MSP430 系列。
|
||||
|
||||
## 认识 Linux 系统
|
||||
|
||||
Linux 可运行于多种平台,比如个人电脑、Power PC 以及 ARM Cortex A 系列 SOC 上。
|
||||
|
||||
Linux 分为内核态和用户态,内核态为受保护的代码,用户态程序执行异常不会导致系统漰溃,是因为用户态只能执行用户权限指令,特权指令只能在内核态执行 (这是由硬件设计决定的),且由于内核态的内存受到硬件保护,因此用户程序的溢出不会导致内核崩溃。内核态和用户态分离的目的就是为了保证系统的稳定,避免丰富的应用程序导致系统死机,而这种情况在 DOS 时期是很常见的。
|
||||
|
||||
由于驱动程序往往需要进行特权操作,比如直接操作物理内存,硬件寄存器,使用中断资源等,因此 Linux 系统的硬件驱动程序需要在内核态执行。Linux 的核心代码很小,在源代码中占大多数的为驱动程序或驱动程序框架。
|
||||
|
||||
为了适应不同类型设备的特征,Linux 内核驱动划分为多个子系统,比如:SPI 子系统、存储子系统、GPU 子系统等。每个子系统都为该类型设备而进行优化设计。同时,许多公司在子系统框架下还会按照自己的产品线构建下一级子系统。
|
||||
|
||||
## Linux 内核源代码目录结构
|
||||
|
||||
* arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386、ARM、PowerPC、MIPS 等。
|
||||
* block:块设备驱动程序 I/O 调度。
|
||||
* Documentation:内核各部分的通用解释和注释。
|
||||
* drivers:设备驱动程序,每个不同的驱动占用一个子目录,如 char、block、net、mtd、i2c 等。
|
||||
* include:头文件,与系统相关的头文件被放置在 include/linux 子目录下。
|
||||
* kernel:内核的最核心部分,包括进程调度、定时器等,而和平台相关的一部分代码放在 arch/*/kernel 目录下。
|
||||
* lib:库文件代码。
|
||||
* net:网络相关代码,实现了各种常见的网络协议。
|
||||
* scripts:包含用于配置内核的脚本文件。
|
||||
* sound:ALSA、OSS 音频设备的驱动核心代码和常用设备驱动。
|
||||
|
||||
## Linux 内核驱动开发的特点
|
||||
|
||||
* 由于驱动运行在内核态,任何错误都有可能导致内核崩溃,因此软件自量的要求很高。
|
||||
* 开发时需要对驱动有所定位,需要清楚驱动在哪个子系统下,属于总线驱动还是设备驱动等。
|
||||
* 内核除为驱动划分了各个子系统外,还将驱动进行了分类,比如:字符设备,块设备,网络设备,杂项设备等。
|
||||
* 与用户态一样,内核中提供了很多同步异步,以及通讯机制,学习 Linux 内核驱动开发时应注意各 API 的学习。
|
||||
* Linux 的内核版本更新很快,不同版本间架构,API 等会有差异,应注意区分。
|
||||
* 内核驱动可以与内核代码编译成一体,称为 Build In,也可以编译成独立模块。
|
||||
* 学习时应注意区分驱动程序的入口,加载时机等。
|
||||
* 内核源码中会使用大量的高级 C 语言宏操作,有些代码比较绕,通常先知道其用途,再深入学习原理。
|
||||
* Linux 内核源码使用 Linux 代码风格进行开发,代码风格应共同遵守。
|
||||
|
||||
## 一个简单的 Linux 内核模块
|
||||
|
||||
```cpp
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
static int hello_init(void)
|
||||
{
|
||||
printk(KERN_ALERT "hello driver enter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hello_exit(void)
|
||||
{
|
||||
printk(KERN_ALERT "hello driver exit\n ");
|
||||
}
|
||||
|
||||
module_init(hello_init);
|
||||
module_exit(hello_exit);
|
||||
MODULE_AUTHOR("rick.chan");
|
||||
MODULE_DESCRIPTION("a simple hello world module");
|
||||
MODULE_ALIAS("a simplest module");
|
||||
```
|
||||
|
||||
其由 C 程序的 include、函数、变量以及诸多 MODULE_* 宏构成,这个程序里没有用户态程序的标准入口 main() 函数。程序的入口由 module_init() 定义,出口由 module_exit() 定义。
|
||||
|
||||
Makefile 文件如下:
|
||||
|
||||
```Makefile
|
||||
obj-m:= \
|
||||
hellodrv.o
|
||||
|
||||
hellodrv-objs:= \
|
||||
hello_drv.o
|
||||
|
||||
EXTRA_CFLAGS += \
|
||||
-I$(PWD)
|
||||
|
||||
all:
|
||||
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||
```
|
||||
|
||||
该程序的编译和使用方式如下:
|
||||
|
||||
```bash
|
||||
make
|
||||
indmod hellodrv.ko
|
||||
lsmod
|
||||
rmmod hellodrv
|
||||
```
|
||||
|
||||
除可使用 indmod 命令加载模块外,还可以使用 modprobe 命令,该命令比 insmod 命令要强大,它在加载某模块时会同时加载该模块所依赖的其他模块。使用 modprobe 命令加载的模块若以:
|
||||
|
||||
```bash
|
||||
modprobe -r <module name>
|
||||
```
|
||||
|
||||
的方式卸载,将同时卸载其依赖的模块。
|
1
Chapter10_Linux_Driver/10.2_内核开发环境的搭建.md
Normal file
1
Chapter10_Linux_Driver/10.2_内核开发环境的搭建.md
Normal file
@ -0,0 +1 @@
|
||||
# 10.2 内核开发环境的搭建
|
1
Chapter10_Linux_Driver/10.3_内核的配置和编译.md
Normal file
1
Chapter10_Linux_Driver/10.3_内核的配置和编译.md
Normal file
@ -0,0 +1 @@
|
||||
# 10.3 内核的配置和编译
|
@ -1 +0,0 @@
|
||||
# 概述
|
Loading…
x
Reference in New Issue
Block a user