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

原创 2012年09月20日 09:06:53
内核树的建立及其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 来使你的代码正确建立。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

关于EXPORT_SYMBOL的作用浅析

在查看内核驱动代码的时候会经常看到在一些函数后面总会跟EXPORT_SYMBOL()这样的宏定义,通过网上查阅,它的作用大致总结如下: 1、定义说明      把内核函数的符号导出,也可以理解成将...

C语言sscanf函数的总结

在处理字符串的程序当中,经常会分析字符串,从一大长串的字符串截取我们需要的数据,这如果通过自己手写函数来分析,虽然可以,但当你知道sscanf的功能,那就自己写函数分析就显得多此一举。 这些函数的使...
  • gzshun
  • gzshun
  • 2011-12-18 16:10
  • 39196

Linux ALSA声卡驱动之七:ASoC架构中的Codec

1.  Codec简介 在移动设备中,Codec的作用可以归结为4种,分别是: 对PCM等信号进行D/A转换,把数字的音频信号转换为模拟信号对Mic、Linein或者其他输入源的模拟信号进...

谈EXPORT_SYMBOL使用

EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static 函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的。2.6就必须用EXPO...

AAC音频编码库FAAC和解码库FAAD移植

AAC音频编码库FAAC和解码库FAAD移植

Linux内核导出符号宏定义EXPORT_SYMBOL的源码分析

源代码: ……. #ifndef MODULE_SYMBOL_PREFIX #define MODULE_SYMBOL_PREFIX "" #endif ……. struct kernel_symb...

wifidog 认证

首先简单介绍一下什么是Portal认证,Portal认证,通常也会叫Web认证,未认证用户上网时,设备强制用户登录到特定站点,用户可以免费访问其中的服务。当用户需要使用互联网中的其它信息时,必须在门户...

翻译:Linux的电源管理架构

设备电源管理 Copyright (c) 2010 Rafael J. Wysocki, Novell Inc. Copyright (c) 2010 Alan Sternstern@rowlan...

Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)

1.  ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。在ASoc出现之...

openwrt 复位功能的实现

1、了解reset按键对应的gpio口,比如gpio10 2、查看芯片手册对应的gpio10是第几组gpio,以及复用的配置标签 3、修改openwrt的dts配置,target/...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)