版权声明:本文为博主原创文章,欢迎转载,转载请注明出处。 https://blog.csdn.net/wangyijieonline/article/details/83996189
最近在搞Linux驱动,出现了很多问题,做一个记录吧。
问题1:编译模块的准备
编译一个模块需要准备以下部分的工具:
<1> 完整可编译并运行到板子上的内核源码,要注意一定要和编内核时使用的完全一样的内核,如果不对编译时可能不会报错,但会在insmod时发生version magic报错。
<2> 交叉编译工具链要准备好,各种交叉编译工具链,常见的有
aarch64-linux-gnu-
arm-linux-gnueabi-
arm-none-eabi
区别见另一篇博客[嵌入式Linux]–arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf、gnueabi区别
<3> 还可能碰见openssl之类的error,自行百度安装相应的库就可以
问题2:内核的准备工作
上边说到要准备好内核源码,这里又有一个问题,是否需要按照板子的实际情况将内核源码进行修改,答案是不需要,但是需要make menuconfig生成一个.config文件和make 编译一次,此外需要修改最顶层的根目录Makefile,将ARCH和CROSS_COMPILE修改
ARCH := arm64
CROSS_COMPILE := aarch64-linux-gnu-
问题3:模块的最基本组成部分
下面是一个最简单的HelloWorld模块程序:
//hello.c文件
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有iomap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数
#include <linux/device.h> //含有类相关的处理函数
int init_hello_module(void)
{
printk("***************Start***************\n");
printk("Hello World Init! \n");
return 0;
}
void exit_hello_module(void)
{
printk("***************End***************\n");
printk("Hello World Exit! \n");
}
module_init(init_hello_module);
module_exit(exit_hello_module);
MODULE_LICENSE("Dual BSD/GPL");//一般放到最后
#Makefile文件
CROSS_COMPILE:= aarch64-linux-gnu-
ARCH:= arm64
CC:= $(CROSS_COMPILE)gcc
LD:= $(CROSS_COMPILE)ld
obj-m := leddriver.o
KERNELDIR = /home/linux-4.9.88
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -f *.o
rm -f *.symvers
rm -f *.order
rm -f *.ko
rm -f *.mod.c