作为一个Linux驱动编程的新手,刚刚开始接触kernel部分,很多东西需要去学习,本身在大学时代硬件基础比较薄弱,现在由于做嵌入式-系统移植的工作,需要涉及很多kernel的知识,kernel不同于android的框架层和上层JAVA应用,需要硬件知识的同时,更多是需要积累,相信通过自己的努力,kernel这块应该可以慢慢学会。现在网上的牛人很多,作为一个新手,开始入门Linux驱动编程,本文仅针对自己做的一些东西总结,当然是很简单的一些东西,但是作为一个新手,即使很多很简单的东西的确需要自己动手去尝试琢磨,才会真正的明白。通过这样的一个实践,很多东西别人说的可能对自己有用,但是不一定都是适合自己的,每个人遇到的问题都是不一样的,所以要多从网上找找资料,从新手开始,自己遇到的问题别人肯定也遇到过,因此,多搜索下,还是可以找到参考的,在此还是要感谢开源的东西以及为开源不断做贡献的各位同仁。
我的Ubuntu版本为10.04,和很多新手一样,今天手动进行了驱动编程最基本的Hello World 模块的加载,关于内核树的建立,网上的资料很多也很详细,如果是Ubuntu系统的,具体可以参考如下两篇博文:
http://forum.ubuntu.org.cn/viewtopic.php?f=97&t=109762
http://blog.youkuaiyun.com/ab198604/article/details/5914203
其中值得引起注意的是,作为Makefile文件,网上复制的要特别注意Makefile格式的问题,不要拿过来就直接用,要看看里面的东西是否跟自己的路径一致,其中需要将$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install 移动到行首 然后按Tab 键自动对齐,这点要引起注意,否则会出现如下错误:make: 没有什么可以做的为 `modules'。这点在给出的第一个网址也有将的很清楚,我也是在这个问题上捣鼓了好久,真是菜啊。
接下来,我要指出的是我本人遇到的第二个问题,加载模块的时候出现的问题:insmod: error inserting 'helloworld.ko': -1 Invalid module format ,这个就尴尬了,模块加载失败,由于我是自己下载的内核源码,没有用之前系统自带的内核,而是我自己构建的内核树,进入/usr/src下可以看到:
linux-headers-2.6.32-21
linux-headers-2.6.32-21-generic
linux-source-2.6.32
linux-source-2.6.32.tar.bz2
第一个和第二个是系统自带的,第三个就是我自己下的内核树。再次进入/lib/modules下可以看到
2.6.32-21-generic
2.6.32.57+drm33.23
通过搜索找到了解决方案:http://blog.youkuaiyun.com/wby0322/article/details/5948615
编译模块的内核源码与当前正在运行的内核源码不同,我的编译模块的内核为2.6.32.57+drm33.23,我当前系统正在运行的内核源码为2.6.32-21-generic,所以出现了insmod: error inserting 'helloworld.ko': -1 Invalid module format 。
Hello.c
很简单,具体如下
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
//必选
//模块许可声明
MODULE_LICENSE("Dual BSD/GPL");
//模块加载函数
static int hello_init(void)
{
printk(KERN_ALERT "hello_init_zw/n");
return 0;
}
//模块卸载函数
static void hello_exit(void)
{
printk(KERN_ALERT "hello_exit_zw/n");
}
//模块注册
module_init(hello_init);
module_exit(hello_exit);
下面的这个很重要,往往出现很多编译错误,都是这个Makefile惹的祸
# Makefile2.6
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
mymodule-objs := hello.o
obj-m := hello.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
注意Makefile中标注地方要用tab空开
root@zw-desktop:/home/zw/hello# make
make -C /lib/modules/2.6.32-21-generic/build M=/home/zw/hello
make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.32-21-generic'
LD /home/zw/hello/built-in.o
CC [M] /home/zw/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/zw/hello/hello.mod.o
LD [M] /home/zw/hello/hello.ko
make[1]:正在离开目录 `/usr/src/linux-headers-2.6.32-21-generic'
root@zw-desktop:/home/zw/hello# insmod hello.ko
root@zw-desktop:/home/zw/hello# lsmod
Module Size Used by
hello 680 0
vmblock 10225 1
vsock 33964 0
root@zw-desktop:/home/zw/hello# rmmod hello
root@zw-desktop:/home/zw/hello# cat /var/log/syslog |grep zw
Apr 9 09:58:51 zw-desktop kernel: [165904.139138] hello_init-zw/n
Apr 9 10:02:43 zw-desktop kernel: [165988.123224] exit_zw/n