参考网上相关资料,现将我在FC6上建立过程归一下
个人用的Linux版本为:FC6/Linux,内核版本为:2.6.18-1.2798.fc6 编译工具:gcc-3.4.1
1.获得Linux内核的源代码,即构建LDD3(Linux Device Drivers 3rd)上面所说的内核树。
假如安装的Linux系统中已自带了源代码的话,应该在/usr/src目录下。假如该
目录为空的话,则需要自己手动下载源代码。下载代码的方法和链接很多,也能够在上通
过去下载。但是,下载的内
核版本最好和所运行的Linux系统的内核版本一致。当然,也能够比Linux系统内核的版
本低,但高的话应该不行(个人尚未实践)。
2.下载完成后,安装在/usr/src下,文档名为:2.6.18-1.2798.fc6-i586.tar.bz2,是个压缩包,解压缩既能够得到整个内核的源代码:
# tar jxvf 2.6.18-1.2798.fc6-i586.tar.bz2
解压后生成一个新的目录/usr/src/2.6.18-1.2798.fc6-i586,任何的源代码都在该目录下。
注:该目录会因内核版本的不同而不同,各位动手实践的朋友只需知道自己的源代码所在的具体位置即可。
3.稍微更改一下Makefile:
每个内核的名字都包含了他的版本号,这也是 uname -r 命令显示的值。内核Makefile 的前四行定义了内核的名字。为了保护官方的内核不被破坏,Makefile
经过了修改,以生成一个和运行中的内核不同的名字。在一个模块插入运行中的内核前,这个模块必须针对运行中的内核进行编译。为此,您必须编辑内核的
Makefile。
例如,假如 uname -r 返回字符串2.6.18-1.2798.fc6,就将 EXTRAVERSION 定义从:
EXTRAVERSION = -prep
修改为:
EXTRAVERSION = -1.2798.fc6
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 18
也就是最后一个连字符后面的任何内容。
4.配置及编译内核。
进入/usr/src/2.6.18-1.2798.fc6-i586/目录下,能够看到Makefile文档,他包含了整个内核树编译信息。该文档最上面四行是关于内核版本的信息。对于整个Makefile能够不用做修改,采用默认的就能够了。
一般情况下,需要先用命令诸如"make menuconfig", "make xconfig"或"make oldcofig"对内核进行配置,这几个都是对内核进行配置的命令,只是他们运行的环境不相同,执行一下这几个命令中的任何一个即可对内核进行配置: make menuconfig是基于界面的内核配置方法,make xconfig应该是基于QT库的,更有make gcofig也是基于图像的配置方法,应该是需要GTK的环境,make oldcofig就是对内核树原有的.config文档进行配置一下即可。
其实内核的配置部分,主要是确保内核启动模块可动态加载的配置,默认配置里面应该已包含了这样的内容,因此,我用的是make menuconfig.
注意:
您的内核必须已启用这些选项进行了编译,用以支持模块的动态加载。
(用make menuconfig调出内核配置菜单):
Loadable module support --->
Enable loadable module support
Module unloading
[ ] Module versioning support (EXPERIMENTAL)
Automatic kernel module loading
注:该步没做时,在make modules时将出错。
Kernel Feautre -> Preemptible Kernel
注:该项为内核抢占式调度配置, 必须确保在构建运行的内核和编译环境的内核时都选上,一般PC机运行的内核已选上了,否则在insmod时将出现如下错误:
# insmod st7565p_driver26.ko
Using st7565p_driver26.ko
st7565p_driver26: version magic '2.6.14.7 ARMv4 gcc-3.4' should be '2.6.14.7 preempt ARMv4
gcc-3.4'
insmod: cannot insert `st7565p_driver26.ko': Invalid module format (-1): Exec format error
在内核源码的目录下执行:
# make
# make bzImage 编译内核
其中,第一个make也能够不执行,直接make bzImage。这个过程可能比较长,因为是对整个内核重新编译了。执行结束后,能够看到在当前目录下生成了一个新的文档: vmlinux, 其属性为-rwxr-xr-x。
然后执行:
# touch * // 时间或时区配置,源代码的时间戳比本机的时间更新,否则产生:make[2]: 警告:检测到时钟错误。您的创建可能是不完整的。
# make modules 编译模块
# make modules_install 安装编译
对内核的任何模块进行编译和安装。完成“内核树”的安装:
执行结束之后,会在/lib/modules下生成新的目录/lib/modules/2.6.18-1.2798.fc6/。 在随后的编译模块文档时,要用到这个路径下的build目录。至此,内核编译完成。 目录“/usr/src/2.6.18-1.2798.fc6-i586/”中就是所谓的“内核代码树”但是“/lib/modules/2.6.18-1.2798.fc6/build”是个符号链接,也指向这个目录,所以这里也能够叫做“内核代码树”,能够重启一下系统。
5.编写模块文档及Makefile
以LDD3上的hello.c为例:
#include
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk("hello,world.\n");
return 0;
}
static void hello_exit(void)
{
printk("Good bye!\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile如下:
obj-m := hello.o
#KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
上面的Makefile是这样确定内核源码树所在的目录的: 我们先到/lib/modules目录, 会看到一些以内核版本为名的目录, 目录中有一个build文档, 他是个符号连接, 指向内核源码树. 那么如何确定进入哪个内核版本的目录呢? 这就能够通过 $ uname -r 来确定, 他指出了当前运行内核的版本.
上面的例子中只讨论了任何的代码在一个文档中的情况. 若代码分布在多个源文档中, 比如file1.c, file2.c, 生成hello.ko. 应该这样写Makefile:
obj-m := hello.o
hello-objs := file1.o file2.o
注意, 虽然我们的目的是生成.ko文档, 但在Makefile中写为.o!
hello.c和Makefile文档应该位于同一个目录下,能够放在/home下。
6.:编译和装载模块
在文档所处的目录下,执行:
# make
然后查看该目录下有哪些文档生成:可见,已生成模块文档hello.ko.
hello.ko
hello.mod.c
hello.mod.o
hello.o
运行命令:
# insmod hello.ko
应该能够看到返回的信息:Hello, world
以通过lsmod来查看模块是否加载进内核
然后再运行命令:
# rmmod hello
应该能够看到返回的信息:Goodbye!
假如没看到,就是输出到系统的日志文档中去了,能够查看文档:
tail –f /var/log/messages
cat /var/log/syslog
应该有信息的输出。
以通过lsmod来查看该模块是否被卸载.
本文来自ChinaUnix博客,假如查看原文请点:http://blog.chinaunix.net/u2/62451/showart_487605.html
阅读(1200) | 评论(0) | 转发(0) |