使用环境 ubuntu18.04桌面版本
原本觉得这类的文章没什么太大的价值,早就被普及。结果明明记起来以前写这么个demo,现在却不知道从何下手,所以这里重新记录一遍,也是作为重新进入linux驱动开发的开篇。
要编译一个hello.ko,我们需要一个已经编译过的内核源码环境,当前我的ubuntu18.04,看来是默认有源码的。
在 /usr/src/目录下有当前release版本的源码文件 (只有目录结构和头文件)
运行命令#uname -r
root@can-virtual-machine:/work/driver/hello# uname
Linux
root@can-virtual-machine:/work/driver/hello# uname -r
4.15.0-50-generic
root@can-virtual-machine:/work/driver/hello# uname --help
用法:uname [选项]...
输出一组系统信息。如果不跟随选项,则视为只附加-s 选项。
-a, --all 以如下次序输出所有信息。其中若-p 和
-i 的探测结果不可知则被省略:
-s, --kernel-name 输出内核名称
-n, --nodename 输出网络节点上的主机名
-r, --kernel-release 输出内核发行号
-v, --kernel-version print the kernel version
-m, --machine print the machine hardware name
-p, --processor print the processor type (non-portable)
-i, --hardware-platform print the hardware platform (non-portable)
-o, --operating-system print the operating system
--help 显示此帮助信息并退出
--version 显示版本信息并退出
GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
请向<http://translationproject.org/team/zh_CN.html> 报告uname 的翻译错误
Full documentation at: <http://www.gnu.org/software/coreutils/uname>
or available locally via: info '(coreutils) uname invocation'
//存在对应的源码
root@can-virtual-machine:/work/driver/hello# ls /usr/src/linux-headers-4.15.0-50-generic/
arch certs Documentation firmware include ipc Kconfig lib mm net scripts sound tools usr zfs
block crypto drivers fs init Kbuild kernel Makefile Module.symvers samples security spl ubuntu virt
参照的《linux设备驱动程序》第二章介绍的hello模块,(这本中文版的,确实如果按照正常阅读习惯很多都读不通顺,所以只能结合上下文“略读”了)。
建一个目录,添加以下两个文件,一个hello.c源文件,和makefile文件。
/*
* hello.c
*/
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT"Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT"Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
#makefile
obj-m:=hello.o
KERNELBUILD :=/lib/modules/$(shell uname -r)/build
default:
make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers *tmp_versions
obj-m后面跟的就是最终的模块名,hello, make 会在该目录下自动找到hello.c文件进行编译
hello模块可能依赖多个文件或者模块,那么在obj-m后面就可以添加下面语句hello-objs:=file.o file1.o
modules目标指向obj-m变量中设定的模块
#make
#insmod ./hello.ko
#lsmod | grep "hello"
#rmmod hello
printk打印的内核信息不会再虚拟终端上输出,一般情况下,kernel信息和sys信息被保存在/var/log/ 目录下的kern.log和sys.log,查看可以看到hello模块加载时的hello world 输出:
#cat /var/log/syslog | head -100 //输出了头100行,看到了hello world, 也可以直接grep