驱动开发-1 模块hello world

来源:互联网 发布:渗透理论 复杂网络 编辑:程序博客网 时间:2024/05/20 03:45

        本文介绍在内核编译模块、加载和卸载模块的过程。

        首先开发环境是Linux-4.4.0+两份代码,hello.c+Makefile。

        这两份代码放到哪里呢?答案是哪里都可以,不过要注意放在一个文件夹下。这个文件夹的位置就是Makefile中的CURRENT_PATH,编译终端在这个文件夹打开就行。

hello.c

/*编写一个helloworld向内核输出*/#include<linux/init.h>/*包含__init和__exit*/#include<linux/module.h>/*必须包含*/MODULE_LICENSE("Dual BSD/GPL");/*许可证,不然加载时会提示该模块污染内核*/static char *name = "yr";static int __init name_init(void){printk("hello world!\n");printk("hello %s!\n", name);return 0;}static void __exit name_exit(void){printk(KERN_INFO"NAME MODULE EXIT\n");}module_init(name_init);/*加载模块时调用初始化函数*/module_exit(name_exit);/*卸载模块时*/module_param(name, charp, S_IRUGO);

        关键部分有注释,不过这离中文注释要当心,博主一开始用的//被报错了。

Makefie如下:

#编译后模块名obj-m:=hello.o #获取当前终端路径CURRENT_PATH:=$(shell pwd)#获取Linux内核路径名 LINUX_KERNEL_PATH:=/usr/src/linux-source-4.4.0all:make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #C 表示进入内核目录读取Makefile; M 表示回到当前目录读Makefileclean:make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

        注意到makefile中的注释是#,$(shell + commond)就是命令行执行commond的效果。大家都清楚内核版本号用uname -r得到,内核源码路径LINUX_KERNEL_PATH怎么办呢?C文件中的可是引用内核中的头文件的。内核源码一般在/usr/src文件夹下,不幸的博主这个文件夹下有好多4.4.0开头的文件,这个方法不奏效。解决方法是在/lib/module/$(shell uname -r)/build,这里妥妥指的就是内核版本号啦。简单说是,如果你不清楚内核代码路径,Makefile中的LINUX_KERNEL_PATH:=/lib/module/$(shell uname -r)/build。


       在这两个文档所在文件下开终端,运行sudo make编译,成功的话,文件下会产生很多新文件,比如这样:

        然而这只是最后的结果,编译过程并没有看上去顺利。小提醒,一个大家可能会遇到的问题:***missing separator . Stop,一般是Makefile文件中两个make那一行开始需要用tab然而你用的是空格。如果用了tab还是会报同样的错——那你大概和博主遇到的问题一样。看看gredit的编辑->首选项->编辑器,把“使用空格代替tab”前面的选项去掉。


        现在已经编译好啦~ sudo insmod ./hello.ko 加载模块,可以使用lsmod看到你的模块,dmesg看到printk的内容。
       sudo rmmod hello卸载模块,lsmod看不到你的hello啦,dmesg可以看到对应printk的内容。

0 0
原创粉丝点击