[架构之路-35]:目标系统 - 系统软件 - Linux OS内核模块与内核设备驱动程序,一切皆文件,Linux虚拟文件系统与统一设备模型
Posted 文火冰糖的硅基工坊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[架构之路-35]:目标系统 - 系统软件 - Linux OS内核模块与内核设备驱动程序,一切皆文件,Linux虚拟文件系统与统一设备模型相关的知识,希望对你有一定的参考价值。
目录
前言:
在实际嵌入式系统中,大多数时候并不需要修改和编写Linux操作系统的代码,而是需要为自己的嵌入式硬件系统编写Linux的设备驱动程序。这是因为,实际的不同应用的嵌入式系统,其硬件设备是不同的,Linux自带的设备驱动程序往往无法满足自身系统的需要。因此,会花几篇文章重点介绍一下Linux下的设备驱动程序。
第1章 嵌入式系统概述
1.1 什么是嵌入式系统
1.2 嵌入式系统的架构
第2章 内核驱动程序架构
2.1 什么驱动程序
驱动程序一般指的是设备驱动程序(Device Driver),是一种可以使计算机和设备进行相互通信的特殊程序。相当于硬件的接口,操作系统只有通过设备驱动程序这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。
因此,驱动程序被比作“ 硬件的灵魂”、“硬件的主宰”、“硬件和系统之间的桥梁”等。
内存也是一种特殊的硬件设备,内存的驱动程序是Linux操作系统自带的,不需要设备厂家额外编写硬件驱动程序。内存的驱动程序包括:uboot、Linux对内存控制器的初始化、Linux内部的内存管理单元MMU。
应用程序只需要通过内存地址就可以直接访问普通的RAM内存。
对于FLASH内存,可以直接通过地址进行“读”访问,但必须要通过特定的驱动程序才能进行"写"访问。
2.2 驱动程序的作用
没有操作系统的单片机就是采用的上述架构。
Linux环境下,采用的就是上述架构。
2.3 Linux下的内核硬件设备驱动程序
(1)Linux设备驱动程序与Linux内核模块
(2)Linux设备驱动程序在内核中的位置
(3)Linux设备驱动程序的特点
第3章 Linux驱动工程师学习路径
3.1 成长之路与必备的知识
(1)嵌入式系统的组成
(2)硬件基础
- 必须熟悉硬件电路的基本组成与原理
- 熟悉SOC芯片的架构与工作原理
- 熟悉特定硬件设备的硬件接口协议
- 熟悉芯片手册
(3)内核编程与编程语言
- Linux系统内核架构
- Linux启动流程
- 汇编语言基础
- C语言基础
- 数据结构基础
(4)Linux设备模型与设备树
(5)Linux驱动程序模型
(6)Linux驱动的主要思想
3.2 C语言基础
3.3 自底向上的构建Linux系统
(1)自底向上构建驱动程序,为应用程序提供访问特定硬件设备的服务。
(2)设备驱动程序的根基是硬件
(3)设备驱动程序运行在内核空间,以两种方式存在:
- 可以动态插入和去除的内核模块
- 与Linux内核的基础代码编译在一起
3.4 字符设备的层次结构
字符设备是Linux内核驱动中,种类最多的一种硬件设备。
3.5 网络驱动的层次结构
第4章 内核模块的动态加载
Linux的大部分的驱动程序是以内核模块的方式存在的。
4.1 什么是内核模块
Linux内核的整体架构本就非常庞大,其包含的组件也非常多,而我们怎样把需要的部分都包含在内核中呢?
如果把需要的所有功能都编译到Linux内核中。这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,将不得不重新编译内核。
有没有另一种机制可使得编译出的内核本身并不需要包含所有功能,而这些功能需要被使用的时候,其对应的代码被动态地加载到内核中呢?
Linux提供了这样的机制,这种机制被称为模块(module)。
模块具有这样的特点:
- 模块本身不被编译人内核映像,从而控制了内核的大小。
- 模块一旦被加载,它就和内核中的其他部分完全一样。
4.2 内核模块的动态加载与静态编译比较
4.3 内核模块的源代码示例
(1)案例1
(2)案例2
/*
* a simple kernel module: hello world
*
* Copyright (C) 2022 liefyuan (liefyuan@qq.com)
*
* Licensed under GPL v2 or later
*/
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_init(void)
printk(KERN_INFO "Hello World enter\\n");
return 0;
module_init(hello_init);
static void __exit hello_exit(void)
printk(KERN_INRO "Hello World exit\\n");
module_exit(hello_exit);
MODULE_AUTHOR("Lief Yuan <liefyuan@qq.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple Hello World Module");
MODULE_ALIAS("a simplest module");
4.4 Linux内核模块程序结构
一个Linux内核模块主要由如下几个部分组成:
(1)模块加载函数:module_init
当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。
(2)模块卸载函数:module_exit
当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块加载函数相关的功能。
(3)模块许可证声明:MODULE_LICENSE
许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(Kernel Tainted)的警告。
(4)模块参数(可选):module_param
模块参数是模块被加载的时候可以传递给它的值,它本身对应模块内部的全局变量。
(5)模块导出符号(可选):export symbol
内核模块可以导出的符号(symbol,对应于函数或变量),若导出,其他模块则可以使用本模块中的变量或函数。
(6)模块作者等信息声明(可选):MODULE_DESCRIPTION
4.5 Makefile与内核模块的编译
(1)案例1
(2)案例2
KERNEL_DIR := "....."
CURRENT_PATH := $(shell pwd)
obj-m := led.o
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
- 第1行,指定内核源码文件目录,使用绝对路径
- 第2行,CURRENT_PATH 表示当前路径,直接通过运行“pwd”命令来获取当前所处路径
- 第3行,obj-m 表示将 led.c 这个文件编译为 led.ko 模块
- 第8行,具体的编译命令,后面的 modules 表示编译模块,-C 表示将当前的工作目录切换到指定目录中,也就是 KERNERLDIR 目录。M 表示模块源码目录,“make modules”命令
- 中加入 M=dir 以后程序会自动到指定的 dir 目录中读取模块的源码并将其编译为.ko 文件。
>> make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
5.6 内核模块的shell操作命令
Linux的模块,以两种方式进入内核:
- 静态编译、连接
- 动态编译、动态插入
(1)查看当前加载的全部模块
>> lsmod
(2)检测模块是否加载
>> ismod
(3)加载新模块
>> insmod
(4)尝试性加载模块
>> modprobe
modprobe和insmod类似,都是用来动态加载驱动模块的,区别在于modprobe可以解决load module的依赖关系,它是通过 /lib/modules/`uname -r`/modules.dep和modules.deo.bb文件来查找依赖关系的;而insmod不能解决依赖关系。
(5)显示模块信息
>> modinfo
(6)卸载模块
>> rmmod
第5章 一切皆文件,Linux虚拟文件系统与统一设备模型
5.1 什么是文件
狭义的文件是指:存储计算机硬盘设备上的信息的组织方式,狭义的文件可以是文本文档、图片、程序等等。
广义的文件是指:存储计算机系统上的信息的组织方式,包括存储在硬盘设备上的信息,存储设备在内存中的信息,甚至可以是存在所有硬件设备中的信息。
Linux中文件,最初是狭义的文件内涵,后来扩展成了广义的文件内涵。
因此,在Linux中,有一句话是这样的:“一切皆文件:everything is file”。
5.2 文件的组织方式:树型结构与Linux虚拟文件系统
5.3 硬件设备的树型组织方式:设备树
一个复杂的嵌入式系统,会支持大量的硬件设备,是按照偏平的方式管理所有的硬件设备,还是分层的方式组织和管理硬件设备呢?
在Linux系统中,采用的是后者,即分层的方式组织硬件设备,在Linux系统中,称为设备树。
5.4 设备也是文件
在Linux中,硬件系统总的总线、总线上的设备,也是以文件的方式来组织和呈现的。
(1)mnt:被映射成硬盘驱动器的硬件设备。
(2)dev:被映射成文件的硬件设备。
(3)sys:被映射成文件的系统信息
(4)proc:被映射成文件的内核信息
(5)temp:内存中的临时性文件,掉电消失
(6)var:经常变化的各种多用户共享文件
(7)bin、sbin:相对稳定不变的系统文件
5.5 虚拟文件系统的用户空间接口
5.6 虚拟文件系统的内核程序
5.7 虚拟文件系统与Dev文件系统
DevFS文件系统是挂接在虚拟文件系统之下的。
5.8 虚拟文件系统与SYSFS/PROC
SYSFS/PROC文件系统是挂接在虚拟文件系统之下的。
以上是关于[架构之路-35]:目标系统 - 系统软件 - Linux OS内核模块与内核设备驱动程序,一切皆文件,Linux虚拟文件系统与统一设备模型的主要内容,如果未能解决你的问题,请参考以下文章
[架构之路-56]:目标系统 - 平台软件 - 总体架构概述
[架构之路-28]:目标系统 - 系统软件 - Linux OS内核功能架构图解内核构建内核启动流程
[架构之路-25]:目标系统 - 系统软件 - bootloader uboot内存映射与启动流程
[架构之路-21]:目标系统 - 系统软件 - 计算机系统架构计算机指令系统结构化程序与分层编程。