序言 【嵌入式|嵌入式linux系统交叉编译内核驱动模块笔记,以一个完全的新手姿势记录】最近终于成功的在自己的手中将一个hello的内核模块成功的编译并加载进自己的嵌入式linux系统,教程翻了无数篇,果然理论的了解和实际上的知道怎么做之间,还存在着很大的差距。。鉴于在查找资料中看到不少的教程中都存在着部分知识缺失的问题,总的来说就是:“我觉得某些东西太过简单我没有必要再讲”,而这一部分又直接导致我一个萌新给完全的给看懵了,因此在这里写一下自己的笔记,着重讲一些当时自己走了弯路的地方。
准备工作 为了能够交叉编译内核驱动,首先你需要:
- 你的对应的硬件平台的内核源码
- 对应硬件平台的交叉编译器
交叉编译器 将交叉编译器放在一个确切的位置,随后在进行工作前需要将它添加到环境变量(可以使用export单独导出,也可以编辑一个setting.sh每次工作前运行一下,甚至可以添加到~/.bashrc中每次启动终端时自动设定)。如果不添加环境变量的话则需要在每次
make
指令后面都手动加上编译器参数和架构参数。常见的配置参数如下,根据自己具体需要进行修改:#!/usr/bin/bash
export ARCH=arm
export CROSS_COMPILE=arm-linux-
内核的编译 要想成功的进行驱动的编译,首先需要有一个成功编译过的内核源码。所以我们需要先进行内核的编译。一般内核需要先通过
make menuconfig
生成内核的编译配置选项。在没有特定需求的时候我们只需要保存退出即可。完成内核的编译配置选项后就可以使用make
进行编译了。注意:使用make之前必须确保架构和交叉编译器的参数都已在环境变量中!驱动编写 接下来到这一步才是正式开始驱动的编译。我们的第一个测试用的驱动,仅仅实现加载和卸载时对内核的消息日志输出。驱动工程的文件夹可以在源码树下,也可以在源码树外的自定义目录,在这里我将驱动工程文件夹放在了源码树外的目录,其文件信息如下:
hello.c
#include
#include static int hello_init(void)
{
printk("Hello kernel world!\n");
return 0;
}static void hello_exit(void)
{
printk("Goodbye world!\n");
}module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("982670455@qq.com>");
MODULE_LICENSE("Dual BSD/GPL");
在内核的编译中,因为不是输出为普通的可执行程序而是输出为内核模块,因此需要独立编写Makefile文件,也建议在进行驱动学习的时候要了解Makefile的简单原理。
Makefile
obj-m:=hello.o
这里是一个最简单没有任何其他功能的Makefile,目的就是把hello.c编译成可加载模块hello.ko文件,当读者进一步了解Makefile机制的时候可以选择添加更多的功能,比如清理等。
驱动编译
在完成以上工程文件后,我们就可以使用这个最简单的Makefile来编译文件了。但是由于编译驱动需要根据内核的源码树进行操作,因此我们在编译的指令中还需要加入内核源码树的目录,然后还要指定编译为模块,最终编译指令如下:
make -C /media/wmd/a1f4b143-42e4-413c-8c1e-bacea116f841/kernel-src/linux-nanopineo/ M=`pwd`modules
其中
-C
后面跟着的就是内核的源码(已经编译过的),而M=则为我们的新模块的目录,由于我们在当前目录下,所以使用内嵌命令pwd
即可得到,最后一个参数modules
指定编译为模块。编译完成后可以看到工作目录下会得到
hello.ko
文件和其他相关文件。文章图片
驱动加载
到了这一步 其实已经很简单了,将编译好的内核模块传输到目标机上,随后在目标机上使用
sudo insmod hello.ko
指令来添加模块。添加完成后可以使用lsmod
来查看模块。使用rmmod
来进行模块的卸载。由于模块除了内核打印日志外没有任何响应,我们可以通过查看内核日志dmesg
的方法来查看内核是否正常工作。文章图片
最终我们可以看到驱动的日志被正常的打印,也就是我们的驱动可以正常的工作!
推荐阅读
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- 【C】题目|【C语言】题集 of ⑥
- 单片机|自学单片机好找工作吗(会单片机能找什么工作?)
- 单片机|keil把源代码生成lib的方法
- c语言|一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc
- c语言|C语言初期学习遇到的特殊点 【三子棋详解】【初学者福音,详细总结,复习能手】
- 笔记|C语言数据结构——二叉树的顺序存储和二叉树的遍历
- 嵌入式-外设|DDR3基础详解
- 个人理解|【C语言基础之类型转换】
- c语言|【C语言】自定义类型 结构体 枚举 联合