日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响(一)

發(fā)布時(shí)間:2025/7/14 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2.4 2.6Linux 內(nèi)核可裝載模

? 塊機(jī)制的改變對(duì)設(shè)備驅(qū)動(dòng)的影響

?? <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

(此文章非常精彩,強(qiáng)烈推薦)

?

2.4 2.6Linux 內(nèi)核在可裝載模塊機(jī)制、設(shè)備模型、一些核心 API 等方面發(fā)生較大改變,設(shè)備驅(qū)動(dòng)開發(fā)人員面臨著將驅(qū)動(dòng)從 2.4 移植到 2.6 內(nèi)核,或是使驅(qū)動(dòng)同時(shí)支持2.4 2.6 內(nèi)核的任務(wù)。站在設(shè)備驅(qū)動(dòng)開發(fā)人員的角度,驅(qū)動(dòng)由一個(gè)或幾個(gè)外部可加載內(nèi)核模塊組成,本文針對(duì) 2.6 內(nèi)核里模塊機(jī)制的改變對(duì)編寫設(shè)備驅(qū)動(dòng)程序的影響,從內(nèi)核模塊的編譯、裝載時(shí)的版本檢查、初始化與退出、模塊使用計(jì)數(shù)、輸出內(nèi)核符號(hào)、命令行輸入?yún)?shù)、許可證聲明等方面比較了 2.4 2.6 內(nèi)核的區(qū)別;并總結(jié)了使設(shè)備驅(qū)動(dòng)同時(shí)支持 2.4 2.6 內(nèi)核的一系列模板。

1. 獲取內(nèi)核版本

當(dāng)設(shè)備驅(qū)動(dòng)需要同時(shí)支持不同版本內(nèi)核時(shí),在編譯階段,內(nèi)核模塊需要知道當(dāng)前使用的內(nèi)核源碼的版本,從而使用相應(yīng)的內(nèi)核 API2.4 2.6 內(nèi)核下,源碼頭文件 linux/version.h 定義有:

LINUX_VERSION_CODE ― 內(nèi)核版本的二進(jìn)制表示,主、從、修訂版本號(hào)各對(duì)應(yīng)一個(gè)字節(jié);

KERNEL_VERSION(major, minor, release) - 由主、從、修訂版本號(hào)構(gòu)造二進(jìn)制版本號(hào)。

在同時(shí)支持2.42.6 內(nèi)核的設(shè)備驅(qū)動(dòng)程序中,經(jīng)常可以看到以下代碼段:


清單1:判斷內(nèi)核版本的代碼段。

#include <linux/version.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)

#define LINUX26

#endif

#ifdef LINUX26

/*code in 2.6 kernel*/

#else

/*code in 2.4 kernel */

#endif

?

?

?

2.內(nèi)核模塊機(jī)制的改變

2.1模塊編譯

2.42.6,外部可裝載內(nèi)核模塊的編譯、連接過程以及Makefile的書寫都發(fā)生了改變。

2.4內(nèi)核中,模塊的編譯只需內(nèi)核源碼頭文件;需要在包含linux/modules.h之前定義MODULE;編譯、連接后生成的內(nèi)核模塊后綴為.o

2.6內(nèi)核中,模塊的編譯需要配置過的內(nèi)核源碼;編譯、連接后生成的內(nèi)核模塊后綴為.ko;編譯過程首先會(huì)到內(nèi)核源碼目錄下,讀取頂層的Makefile文件,然后再返回模塊源碼所在目錄。


清單22.4 內(nèi)核模塊的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 內(nèi)核下內(nèi)核模塊的Makefile與普通用戶程序的Makefile在結(jié)構(gòu)和語法上都相同但是必須在CFLAGS中定義-D__KERNEL__-DMODULE指定內(nèi)核頭文件目錄-I$(KDIR)/include 有一點(diǎn)需注意,之所以在CFLAGS中定義變量,而不是在模塊源碼文件中定義,一方面這些預(yù)定義變量可以被模塊中所有源碼文件可見,另一方面等價(jià)于將這些預(yù)定義變量定義在源碼文件的起始位置。在模塊編譯中,對(duì)于這些全局的預(yù)定義變量,一般在CFLAGS中定義。


清單32.6 內(nèi)核模塊的Makefile模板

# 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是在內(nèi)核源碼的頂層Makefile中定義的一個(gè)變量,在第一次讀取執(zhí)行此Makefile時(shí),KERNELRELEASE沒有被定義, 所以make將讀取執(zhí)行else之后的內(nèi)容。如果make的目標(biāo)是clean,直接執(zhí)行clean操作,然后結(jié)束。當(dāng)make的目標(biāo)為all時(shí),-C $(KDIR) 指明跳轉(zhuǎn)到內(nèi)核源碼目錄下讀取那里的MakefileM=$(PWD) 表明然后返回到當(dāng)前目錄繼續(xù)讀入、執(zhí)行當(dāng)前的Makefile。當(dāng)從內(nèi)核源碼目錄返回時(shí),KERNELRELEASE已被被定義,kbuild也被啟動(dòng)去解析kbuild語法的語句,make將繼續(xù)讀取else之前的內(nèi)容。else之前的內(nèi)容為kbuild語法的語句, 指明模塊源碼中各文件的依賴關(guān)系,以及要生成的目標(biāo)模塊名。mymodule-objs := file1.o file2.o表示mymoudule.o file1.ofile2.o 連接生成。obj-m := mymodule.o表示編譯連接后將生成mymodule.o模塊。

補(bǔ)充一點(diǎn),"$(MAKE) -C $(KDIR) M=$(PWD)""$(MAKE) -C $(KDIR) SUBDIRS =$(PWD)"的作用是等效的,后者是較老的使用方法。推薦使用M而不是SUBDIRS,前者更明確。

通過以上比較可以看到,從Makefile編寫來看,在2.6內(nèi)核下,內(nèi)核模塊編譯不必定義復(fù)雜的CFLAGS,而且模塊中各文件依賴關(guān)系的表示簡潔清晰。


清單4: 可同時(shí)在2.4 2.6 內(nèi)核下工作的Makefile

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

?

?

2.2模塊裝載時(shí)的版本檢查

Linux內(nèi)核一直在更新、完善,在a版本內(nèi)核源碼下編譯的模塊在b版本內(nèi)核下通常不能運(yùn)行,所以必須有一種機(jī)制,限制在a版本內(nèi)核下編譯生成的模塊在b版本內(nèi)核下被加載。

2.42.6內(nèi)核在可裝載內(nèi)核模塊的版本檢查機(jī)制方面發(fā)生了根本性的改變,不過這些改變對(duì)設(shè)備驅(qū)動(dòng)開發(fā)人員而言基本是透明的。為了使模塊裝載時(shí)的版本檢查機(jī)制生效,2.4 內(nèi)核下,只需在CFLAGS中定義

?

-DMODVERSIONS -include $(KDIR)/include/linux/modversions.h

?

2.6內(nèi)核下,開發(fā)人員無須采用任何操作。

不過,在此仍有必要闡明2.42.6內(nèi)核對(duì)可加載模塊的版本檢查機(jī)制。

2.4內(nèi)核下, 執(zhí)行`cat /proc/ksyms`可看到內(nèi)核符號(hào)在名字后還跟隨著一串校驗(yàn)字符串,此校驗(yàn)字符串與內(nèi)核版本有關(guān)。在內(nèi)核源碼頭文件linux/modules 目錄下存在許多*.ver文件,這些文件起著為內(nèi)核符號(hào)添加校驗(yàn)后綴的作用,如ksyms.ver 文件里有一行 #define printk _set_ver(printk)linux/modversions.h 文件會(huì)包含全部的 ver文件 。所以當(dāng)模塊包含linux/modversions.h文件后,編譯時(shí),模塊里使用的內(nèi)核符號(hào)實(shí)質(zhì)是帶有校驗(yàn)后綴的內(nèi)核符號(hào)。在加載模塊時(shí),如果模塊中所使用內(nèi)核符號(hào)的校驗(yàn)字符串與當(dāng)前運(yùn)行內(nèi)核所導(dǎo)出的相應(yīng)的內(nèi)核符號(hào)的校驗(yàn)字符串不一致,即當(dāng)前內(nèi)核空間并不存在模塊所使用的內(nèi)核符號(hào),就會(huì)出現(xiàn)"Invalid module format "的錯(cuò)誤。

為內(nèi)核符號(hào)添加校驗(yàn)字符串來驗(yàn)證模塊的版本與內(nèi)核的版本是否匹配是繁雜和浪費(fèi)內(nèi)核空間的;而且隨著SMP(對(duì)稱多處理器)、PREEMPT(可搶占內(nèi)核)等機(jī)制在2.6內(nèi)核的引入和完善,模塊運(yùn)行時(shí)對(duì)內(nèi)核的依賴不僅取決于內(nèi)核版本,還取決于內(nèi)核的配置,此時(shí)內(nèi)核符號(hào)的校驗(yàn)碼是否一致不能成為判斷模塊可否被加載的充分條件。2.6 內(nèi)核下,在linux/vermagic.h中定義有VERMAGIC_STRINGVERMAGIC_STRING不僅包含內(nèi)核版本號(hào),還包含有內(nèi)核使用的gcc版本,SMPPREEMPT等配置信息。模塊在編譯時(shí),我們可以看到屏幕上會(huì)顯示"MODPOST"。在此階段, VERMAGIC_STRING會(huì)添加到模塊的modinfo段。 在內(nèi)核源碼目錄下scripts\mod\modpost.c文件中可以看到模塊后續(xù)處理部分的代碼。模塊編譯生成后,通過`modinfo mymodule.ko`命令可以查看此模塊的vermagic等信息。2.6 內(nèi)核下的模塊裝載器里保存有內(nèi)核的版本信息,在裝載模塊時(shí),裝載器會(huì)比較所保存的內(nèi)核vermagic與此模塊的modinfo段里保存的vermagic信息是否一致,兩者一致時(shí),模塊才能被裝載。譬如Fedora core 4 core 2 使用的都是2.6 版本內(nèi)核, 在Fedore Core 2下去加載Fedora Core4下編譯生成的hello.ko,會(huì)出現(xiàn)"invalid module format" 錯(cuò)誤。

?

insmod hello.ko

Invalid module format

hello: version magic '2.6.11-1.1369_FC4 686 REGPARM 4KSTACKS gcc-4.0'

should be '2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3'

?

2.3模塊的初始化與退出

2.6內(nèi)核中,內(nèi)核模塊必須調(diào)用宏module_init module_exit() 去注冊(cè)初始化與退出函數(shù)。在2.4 內(nèi)核中,如果初始化函數(shù)命名為init_module()、退出函數(shù)命名為cleanup_module(),可以不必使用module_init module_exit 宏。推薦使用module_init module_exit宏,使代碼在2.42.6內(nèi)核中都能工作。


清單5:適用于2.42.6內(nèi)核的模塊的初始化與退出模板

#include <linux/module.h>? /* Needed by all modules */

#include <linux/init.h>??? /* Needed for init&exit macros */

static int mod_init_func(void)

{

/*code here*/

return 0;

}

static void mod_exit_func(void)

{

/*code here*/

}

module_init(mod_init_func);

module_exit(mod_exit_func);

?

需要注意的是初始化與退出函數(shù)必須在宏module_initmodule_exit使用前定義,否則會(huì)出現(xiàn)編譯錯(cuò)誤。

?

?

轉(zhuǎn)載于:https://blog.51cto.com/zyg0227/270373

總結(jié)

以上是生活随笔為你收集整理的从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。