博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux 2.4和2.6内核模块编译的差别
阅读量:4138 次
发布时间:2019-05-25

本文共 4008 字,大约阅读时间需要 13 分钟。

Linux 2.4和2.6内核模块编译的差别

 
(2006-02-25 22:31:40)
从2.4到2.6,外部可装载内核模块的编译、连接过程以及Makefile的书写都发生了改变

2.4内核中,模块的编译只需内核源码头文件;需要在包含linux/modules.h之前定义MODULE;编译、连接后生成的内核模块后缀为.o。

2.6内核中,模块的编译需要配置过的内核源码;编译、连接后生成的内核模块后缀为.ko;编译过程首先会到内核源码目录下,读取顶层的Makefile文件,然后再返回模块源码所在目录。

#Makefile2.4 KVER=$(shell uname -r) KDIR=/lib/modules/$(KVER)/build OBJS=mymodule.o CFLAGS=-D__KERNEL__ -I$(KDIR)/include -DMODULE -D__KERNEL_SYSCALLS__ -DEXPORT_SYMTAB -O2 -fomit-frame-pointer -Wall -DMODVERSIONS -include $(KDIR)/include/linux/modversions.h all: $(OBJS) mymodule.o: file1.o file2.o ld -r -o $@ $^ clean: rm -f *.o

在2.4 内核下,内核模块的Makefile与普通用户程序的Makefile在结构和语法上都相同,但是必须在CFLAGS中定义-D__KERNEL__-DMODULE,指定内核头文件目录-I$(KDIR)/include。 有一点需注意,之所以在CFLAGS中定义变量,而不是在模块源码文件中定义,一方面这些预定义变量可以被模块中所有源码文件可见,另一方面等价于将这些预定义变量定义在源码文件的起始位置。在模块编译中,对于这些全局的预定义变量,一般在CFLAGS中定义。

# Makefile2.6 ifneq ($(KERNELRELEASE),) #kbuild syntax. dependency relationshsip of files and target modules are listed here. mymodule-objs := file1.o file2.o obj-m := mymodule.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

KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义, 所以make将读取执行else之后的内容。如果make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句, 指明模块源码中各文件的依赖关系,以及要生成的目标模块名。mymodule-objs := file1.o file2.o表示mymoudule.o 由file1.o与file2.o 连接生成。obj-m := mymodule.o表示编译连接后将生成mymodule.o模块。

补充一点,"$(MAKE) -C $(KDIR) M=$(PWD)"与"$(MAKE) -C $(KDIR) SUBDIRS =$(PWD)"的作用是等效的,后者是较老的使用方法。推荐使用M而不是SUBDIRS,前者更明确。

通过以上比较可以看到,从Makefile编写来看,在2.6内核下,内核模块编译不必定义复杂的CFLAGS,而且模块中各文件依赖关系的表示简洁清晰。

#Makefile for 2.4 & 2.6 VERS26=$(findstring 2.6,$(shell uname -r)) MAKEDIR?=$(shell pwd) ifeq ($(VERS26),2.6) include $(MAKEDIR)/Makefile2.6 else include $(MAKEDIR)/Makefile2.4 endif

 

内核模块可以通过modinfo命令查看模块的vermagic等信息

   
2009-10-09 10:13:03

分类: LINUX

1.1         example1

#define MODULE

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

MODULE_LICENSE("GPL");

static int __init lkp_init(void)

{

printk("<1>hello world from the kernel space.. \n");

return 0;

}

static void __exit lkp_cleanup(void)

{

printk("<2>goodbye world, leaving kernel space.. \n");

}

module_init(lkp_init);

module_exit(lkp_cleanup);

以上是源代码,2.4内核中动态可加载模块文件开始出一定要有一个MODULE宏定义,不然会出现版本不匹配等错误,

__init告知编译程序相关的函数和变量只用于初始化,编译程序将标有__init的所有代码存储到特殊的内存中,初始化结束后就释放这段内存,同样宏__exit__exitdata仅用于退出和关闭例程,

代码中的最后两行module_init(lkp_init);module_exit(lkp_cleanup);可以不用加入,但这样的话模块在加入和移除时将不会调用lkp_init, lkp_cleanup,则文件/var/log/message中将不包含提示信息,如果不想使用这种方法,可以使用下面的代码

 

1.2         example2

#define MODULE

#include <linux/module.h>

MODULE_LICENSE("MYGPL");

 int init_module(void)

{

    printk("<1>Hello, world\n");

    return 0;

 }

 void cleanup_module(void)

 {

     printk("<1>Goodbye cruel world\n");

 }

在此代码中可以直接将example1中的初始化和退出函数名字直接改为init_modulecleanup_module,这样内核在加载和移除该模块时自动调动初始化和清除函数.

 

1.3         example3

#define MODULE

#include <linux/kernel.h>

#include <linux/module.h>

MODULE_LICENSE("GPL");

int init_module(void)

{

printk("<1>hello \n");

return 0;

}

void cleanup_module(void)

{

printk("<1>bye \n");

}

 

1.4         makefile文件

#Makefile for linux loadable kernel module

CC=gcc

CFLAG := -I/usr/src/linux-2.4.20-8/include -D__KERNEL__ -D__MODULE -O -Wall

OBJ=test

$(OBJ).o:$(OBJ).c

      -rm $@ -f

      $(CC) $(CFLAG) -c $(OBJ).c -o test.o

 

注意其中的gcc选项一定要包含D_KERNEL__ D__MODULE这两个选项,不管对于什么的架构,一定要使gcc在编译时的环境版本和运行时的环境版本相匹配,也即在运行环境中,假如你使用ARM或者2.4.20-8这些个版本,那么在编译时所用的头文件也一定要是2.4.20-8这个版本的,不然会导致版本不匹配,其中的-I/usr/src/linux-2.4.20-8/include可以用-I/usr/src/’uname -r’/include 来代替,

MODULE_LICENSE("GPL");本句代码可以不要,但不要的话,运行时会出现"hello: module license 'unspecified' taints kernel.",词典上对taints的解释是"感染,污点".

1.5         编译过程

在命令行输入make命令编译生成ELF文件,

insmod hellomod来加载模块

rmmod hellomod移除hellomod模块

lsmod查看当前已加载模块

hellomod向模块发出的信息可以在/var/log/message文件中查看到,

可用dmesg命令来查看

readelfojbdump用于查看目标文件的信息

转载地址:http://enhvi.baihongyu.com/

你可能感兴趣的文章
第四章 微信飞机大战
查看>>
九度:题目1008:最短路径问题
查看>>
九度Online Judge
查看>>
九度:题目1027:欧拉回路
查看>>
九度:题目1012:畅通工程
查看>>
九度:题目1017:还是畅通工程
查看>>
九度:题目1034:寻找大富翁
查看>>
第六章 背包问题——01背包
查看>>
第七章 背包问题——完全背包
查看>>
51nod 分类
查看>>
1136 . 欧拉函数
查看>>
面试题:强制类型转换
查看>>
Decorator模式
查看>>
Template模式
查看>>
Observer模式
查看>>
高性能服务器设计
查看>>
性能扩展问题要趁早
查看>>
MySQL-数据库、数据表结构操作(SQL)
查看>>
OpenLDAP for Windows 安装手册(2.4.26版)
查看>>
图文介绍openLDAP在windows上的安装配置
查看>>