内核树的建立及其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 来使你的代码正确建立。

linux 第一个内核模块Hello World

 内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个...
  • blank_bird
  • blank_bird
  • 2011-06-12 01:03:00
  • 4136

添加内核模块之入门helloworld.ko

首先 是从一个西邮学生看到的,比较好的入门方式:首先是hello.c的文件:主要要说明对内核的编程只能使用内核头文件,所以通常我们都使用makefile来控制编译过程#include "linux/i...
  • alexmahone_xie
  • alexmahone_xie
  • 2011-01-05 21:45:00
  • 2263

Linux---我的第一个内核模块之Hello World

1、什么是内核模块? 内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),简称为模块。Linux内核之所以提供模块机...
  • L_in12
  • L_in12
  • 2015-11-04 17:24:38
  • 1049

编写一个简单的内核模块程序Hello World!

一、Linux内核模块基本原理Linux 内核模块(LKM)是一些在启动的操作系统内核需要时可以载入内核执行的代码块,不需要时由操作系统卸载。它们扩展了操作系统内核功能却不需要重新编译内核、启动系统。...
  • sh21_
  • sh21_
  • 2017-03-09 16:47:34
  • 4079

ubuntu 第一个Hello world模块编译(本机运行)

什么是模块 概念 模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行(但它实际上并不是内核的一部分),这与运行在用户空间的进程是不同的。...
  • wait_for_taht_day5
  • wait_for_taht_day5
  • 2015-12-25 17:44:05
  • 1473

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

作为一个Linux驱动编程的新手,刚刚开始接触kernel部分,很多东西需要去学习,本身在大学时代硬件基础比较薄弱,现在由于做嵌入式-系统移植的工作,需要涉及很多kernel的知识,kernel不同于...
  • gnahzlinux
  • gnahzlinux
  • 2012-04-07 17:51:06
  • 462

Linux 最简单内核模块 Hello World 示例

注:如果想要按照本篇实践,需要有能运行的arm开发板和对应版本的内核(如果想在Linux主机上编译运行,请参考附1) 1. 在相应版本内核的driver目录下新建如下文件: module fil...
  • chinaeran
  • chinaeran
  • 2015-04-28 08:38:33
  • 6280

64位Ubuntu14.04系统下加载内核模块hello world

64位Ubuntu14.04系统下加载内核模块hello world
  • Lucien_zhou
  • Lucien_zhou
  • 2017-05-06 17:48:46
  • 1683

HelloWorld模块加载--驱动

#include #include MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(...
  • KidLeaf2
  • KidLeaf2
  • 2011-10-20 21:19:08
  • 3107

linux内核驱动---hello_world驱动加载

关于linux驱动的加载有两种方法:       一种是通过直接将驱动编译进内核,这种方法避免了驱动版本和内核版本不一致的问题,但会使内核增大,并且日后修改也不方便,因为每改动一个小功能就要重新编译内...
  • plus1993
  • plus1993
  • 2015-09-23 16:20:09
  • 612
收藏助手
不良信息举报
您举报文章:内核树的建立及其Hello World 模块的加载
举报原因:
原因补充:

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