关闭

内核树的建立及其Hello World 模块的加载

1432人阅读 评论(0) 收藏 举报
分类:
内核树的建立及其Hello World 模块的加载
       每每到了一定程度过后,对自己所做过的事,看过的书等做一些总结是很有必要的。初学驱动编程,面对的第一个难题就是这个驱动编程该怎么学,入门是关键。在前辈们推荐下和在网上搜索中,得出结论:不知道怎么学和该学些什么,那就看这两本书:O'REILLY写的《LINUX设备驱动程序》和宋宝华的《LINUX设备驱动程序(第3版)》,或者你有兴趣的话把这本书《嵌入式Linux应用程序开发标准教程(华清远见)》也看了。学习的过程不能只看书,需要在理论和实践中获得进步。下面是我在学习过程中做的一些总结。
内核树的建立
       我在一开始就遇到了第一个问题就是:为什么要建立内核树?内核树就是在网上下载内核源代码编译过后的文件,简单地可以理解为我们在编译驱动模块时需要用到的一些依赖文件,也就是一些库相关的,也可以说是一种驱动模块编译环境。由此又有新的问题:难道我们的Linux系统不能提供驱动模块编译的环境吗?答案是否定的,当然发布的Linux肯定是提供了这样一套驱动模块编译的环境的,但是发布的Linux为了使系统变得很轻量级,不得不把一些臃肿的不是必须的工具、文件等都删掉了。这就是我们为什么要建立内核树,因为它提供了调试内核模块等功能。
在明白了第一个问题过后,我需要做的就是如何把下载好的源代码编译成内核树。首先,我们需要下源码,最好下载对应系统版本号的源码:
查看内核版本:uname –r    --->  2.6.32-41-generic(我的内核版本)
得到对应的源码:
sudo apt-cache search linux-source
sudo apt-get install linux-source-2.6.32
下载完过后,在/usr/src/ 下面有个对应的压缩包,解压过后进入linux-source-2.6.32
此时要对内核编译进行配置:oldconfig、 menuconfig、 xconfig 选择其中一种就行了,一般用:make menuconfig 现在只是搭建内核树,因此不用怎么改,直接保存就行了。
而后就开始编译:
make
make bzImage
结束后生成:vmlinux 其属性为:-rwxr-xr-x
到这里,要进行加载内核模块编译,需要root用户
make modules  /* 编译内核经常会用到的 */
make modules_install /* 安装模块 */
执行结束后,会在/lib/modules下生成新的目录
在随后的编译模块文件时,要用到这个路径下 的build目录,至此内核编译完成,可以重启一下系统。
Hello World 模块的加载
就拿《Linux设备驱动》上的那个hello world为例吧:
#include <linux/init.h>
#include <linux/module.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文件:
ifeq($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd) 
modules: 
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
modules_install: 
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm –rf *.o *~ core *.cmd *.ko *.mod.c: modules modules_install clean
else
obj-m :=hello.o
endif
然后再目录下make一下,我在这里出现过很多问题:主要是有编译时的内核路径不对的,你也可以在到/lib/modules/目录下看有哪些内核路径,修改成自己相应的就行了;还有就是$(MAKE)前面是用的tab键而不是空格。
编译完成后,会生成个.ko文件,这个就是要的模块的文件,后来要做到任务就是将这个模块加载到内核中:
sudo insmod ./hello.ko
加载之前,可以先执行:cat /var/log/messages 查看系统消息;
加载完成过后:lsmod 或者cat /proc/devices | grep hello
卸载模块:rmmod hello
在加载过程中常常会遇到这个问题:
insmod: error inserting 'helloworld.ko': -1 Invalid module format
一个原则就是下载的内核源码与具体要使用加载模块的内核环境版本要一致。
一些说明:
       如果你需要编译一个模块给一个特定的内核版本, 你将需要使用这个特定版本的建立系统和源码树. 前面展示过的在例子 makefile 中简单修改 KERNELDIR 变量, 就完成这个动作。
       内核接口在各个发行之间常常变化. 如果你编写一个模块想用来在多个内核版本上工作(特别地是如果它必须跨大的发行版本), 你可能只能使用宏定义和 #ifdef 来使你的代码正确建立。
2
1

猜你在找
深度学习基础与TensorFlow实践
【在线峰会】前端开发重点难点技术剖析与创新实践
【在线峰会】一天掌握物联网全栈开发之道
【在线峰会】如何高质高效的进行Android技术开发
机器学习40天精英计划
Python数据挖掘与分析速成班
微信小程序开发实战
JFinal极速开发企业实战
备战2017软考 系统集成项目管理工程师 学习套餐
Python大型网络爬虫项目开发实战(全套)
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:116487次
    • 积分:1481
    • 等级:
    • 排名:千里之外
    • 原创:27篇
    • 转载:6篇
    • 译文:0篇
    • 评论:25条
    最新评论