1.内核下载地址
Linux内核源码的官方网站为https://www.kernel.org/,可以在该网站下载最新的Linux内核源码。进入该网站之后如下图所示:
从上图可以看到多个版本的内核分支,分别为主线版本(mainline)、稳定版本(stable)和长期支持版本(longterm)。以上各个支线和主线是由linus torvalds(Linux之父)所领导。半导体厂商和一些内核爱好者会在官网下载相应版本的内核源码,对该源码进行打补丁等操作。以此让官网的内核源码可以在半导体厂家设计的主控(CPU)上跑起来,所以在开发和学习的过程中,我们并不会直接去Linux内核官网下去下载源码,而且是使用半导体厂家提供的源码包。
2.内核源码结构
3.内核编译(内核源码编译过再进行驱动开发)
使用命令“./build.sh kernel”进行内核源码的编译,其他SDK包kernal使用厂商编写的脚本进行编译如./make.sh
4.驱动的基本框架
Linux驱动的基本框架主要由模块加载函数,模块卸载函数,模块许可证声明,模块参数,模块导出符号,模块作者信息等几部分组成,其中模块参数,模块导出符号,模块作者信息是可选的部分,也就是可要可不要。剩余部分是必须有的。
- 模块加载函数:当使用加载驱动模块时,内核会执行模块加载函数,完成模块加载函数中的初始化工作。
- 模块卸载函数:当卸载某模块时,内核会执行模块卸载函数,完成模块卸载函数中的退出工作。
- 模块许可证声明:许可证声明描述了内核模块的许可权限,如果不声明模块许可,模块在加载的时候,会收到“内核被污染(kernel tainted)”的警告。可接受的内核模块声明许可包括“GPL”“GPL v2”。
5.hello简单驱动编写
#include<linux/module.h>
#include<linux/kernel.h>
static int __init hellow_init(void)
{
printk(KERN_INFO "Hello, world!\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye, world!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("wjw");
模块加载函数如下:
static int __init hellow_init(void)
{
printk(KERN_INFO "Hello, world!\n");
return 0;
}
module_init(hello_init);
模块卸载函数如下:
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye, world!\n");
}
module_exit(hello_exit);
模块许可生命函数如下:
MODULE_LICENSE("GPL v2");
6.编写Makefile
#1.设置ARCH变量为arm64
export ARCH=arm64
#2.设置交叉编译器前缀为aarch64-linux-gnu-
export CROSS_COMPILE= home/RK3568_SDK/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
#3.内核源码路径
KERNELDIR := /home/RK3568_SDK/kernel
#4.obj-m += <文件>:将指定的文件(需要是以.o结尾)设为编译时以模块形式编译
obj-m := hello.o
CURRENT_PATH := $(shell pwd)
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
7.编译
执行make进行编译,输入hello.ko驱动模块,如下图
8.驱动加载与载卸载
在开发板上通过“insmod hello.ko”或modprobe hello.ko(更智能,将驱动依赖的驱动也进行加载)命令可以加载驱动,在加载驱动模块的时候会执行驱动入口的函数,也就是hello程序中的hello_init函数,可通过lsmod查看加载的驱动模块。注:也可以将驱动编译进内核(不推介)
卸载hello内核模块,可以通过“rmmod hello”命令来卸载驱动模块,同理在卸载驱动模块的时候会执行驱动出口的函数,所以可以看到驱动出口函数打印出来的字符串信息“hello_exit”