First Linux Device Driver
预备环境
在原文链接中给出了 ubuntu 环境、树莓派环境、比格板环境的搭建指南,可以参考搭建,最好使用推荐的比格板,因为后面会涉及到设备驱动,比格板嵌入式平台方便扩展。
第一个 Linux 设备驱动
模块信息
- 证数
- 作者
- 模块描述
- 模块版本
证书
GPL: GNU General Public License
,是软件的一种开源证数。如果你的软件具有 GPL
证书,那么它是自由软件。自由软件并不意味着是免费的软件,它也可以是付费软件。下面的证书是当前可以用来表明软件是自由软件的证书。
GPL: GNU Public License v2 or Later
GPL v2: GNU Public License v2
GPL and additional rights: GNU Public License v2 rights and more
Dual BSD/GPL: GNU Public License v2 or BSD license choice
Dual MIT/GPL: GNU Public License v2 or MIT license choice
Dual MPL/GPL: GNU Public License v2 or Mozilla license choice
上面的一些证书是双证书,但是在 Linux
下运行时,它就是 GPL
证书。证书存在有多重意义:
- 用户可以使用
modinfo
展示证书信息,表示这个软件是自由软件 - 社区可以用它来避免侵权
- 供应商可以按照自己的意愿来提供软件
我们可以按照下面的方式指定模块的证书,实现下面的操作,首先要包含 Linux/module.h
头文件:
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("Dual BSD/GPL");
证书并不是强制要求的,不过还是建议在自己的软件中使用证书。
作者
使用这个宏,我们可以知道软件是由谁写的,这样使用 modinfo
就能够将作者名称展示出来:
MODULE_AUTHOR("Author");
同样的,需要包含 linux/module.h
头文件,我们可以将自己的邮件写到这个位置,如果有多个作者,可以使用多个 MODULE_AUTHOR
宏来展示。
模块描述
使用这个宏,我们可以展示软件的一些详细信息,这样使用 modinfo
就能够将模块的描述信息展示出来:
MODULE_DESCRIPTION("A sample driver");
同样的,需要包含 linux/module.h
头文件。
模块版本
使用这个宏,我们可以展示软件的版本信息,使用 modinfo
将会展示这一信息:
MODULE_VERSION("2:1.0");
简单内核模块编程
所有的程序都需要有入口点与退出点。在编写内核程序时,入口点与退出点分别是如下两个函数:
- 初始化函数
- 退出函数
需要注意的是,内核模块使用的头文件与用户空间程序头文件有所区别。内核模块代码不能调用用户空间库/API/系统调用。
初始化函数
当设备驱动加载到内核中时,比如使用 insmod
插入内核时,会首先执行这个函数。下面是这类函数的形式:
static int __init hello_world_init(void)
{
return 0;
}
module_init(hello_world_init);
这个函数通过 module_init
宏注册。
退出函数
当卸载设备驱动时,比如使用 rmmod
卸载模块时,会在收尾阶段执行这个函数,下面是这类函数的形式:
void __exit hello_world_exit(void)
{
}
module_exit(hello_world_exit);
这个函数通过 module_exit
宏注册。
printk
在内核中,可以使用 printk
接口打印不同等级的日志信息,下面是这个函数的使用方式:
printk(KERN_INFO "Test printk %dst time", 1);
可以使用的打印等级有:
KERN_EMERG
KERN_ALERT
KERN_CRIT
KERN_ERR
KERN_WARNING
KERN_NOTICE
KERN_INFO
KERN_DEBUG
在较新版本的内核中,除 printk
外,可以使用下面的接口打印日志:
pr_info
,打印一个KERN_INFO
等级的日志信息pr_cont
,在同一行打印日志信息pr_debug
,打印一个KERN_DEBUG
等级的日志信息pr_err
,打印一个KERN_ERR
等级的日志信息pr_warn
,打印一个KERN_WARN
等级的日志信息
第一个设备驱动
下面是我们第一个设备驱动:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_world_init(void)
{
printk(KERN_INFO "Welcome to Linux Kernel Module\n");
return 0;
}
static void __exit hello_world_exit(void)
{
printk(KERN_INFO "Linux Kernel Module Bye\n");
}
module_init(hello_world_init);
module_exit(hello_world_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("^_^");
MODULE_DESCRIPTION("First Linux Kernel Module");
MODULE_VERSION("1:1.0");
编译驱动
可以使用下面的 Makefile
直接编译:
obj-m += hello_world_module.o
KDIR = /lib/modules/$(shell uname -r)/build
all:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=$(shell pwd) clean
加载/卸载驱动
加载
sudo insmod hello_world_module.ko
列出模块
lsmod | grep hello
卸载
sudo rmmod hello_world_module
获取模块详细信息
modinfo hello_world_module.ko
标签:GPL,第一个,module,KERN,MODULE,world,驱动,hello
From: https://www.cnblogs.com/arvin-blog/p/18021942