
详解Linux操作系统设备驱动兼容性
发布时间:2006-10-13 12:22:18 来源:天极博客 网友评论 0 条最新进展
Linux一直在迅速地发展着,开发人员总是迫切希望改善核心内部,它们并不考虑向后兼容性。这种自由开发导致了不同版本核心提供的设备驱动程序接口之间一定程度的不兼容。不过,在应用级还保持着兼容,除了个别需要与核心特征进行低级交互的应用(象ps)。
另一方面,设备驱动程序是直接链接到核心映象上的,因此必须与数据结构、全局变量、以及由内系统引出的函数发生的改变保持一致。在开发过程中,随着新特征的加入,内部被修改;新的实现取代了就的实现,因为实践证明它们更快,更清晰。尽管不兼容性要求程序员在写模块时要做一些额外的工作,我认为连续的开发是Linux社区的成功点:严格的先后兼容性最终证明是有害的。
这一章讲述2.0.x和2.1.43之间的不同,这些将会与即将推出的2.2发布类似。Linus在前几个2.1版本中引入了最重要的改变,这样核心就可以多经历几个2.1版本,使得驱动程序的作者有足够的时间在开发被锁定以发布稳定的2.2之前来稳定驱动程序。下面的小节介绍驱动程序是如何处理2.0和2.1.43之间的不同的。我已经修改了本书介绍的所有示例代码,使得它们可以同时在2.0和2.1.43上编译和运行,以及这之间的大多数版本。驱动程序的新版本可以从O’Reilly的FTP站点上在线例子的v2.1目录下得到。2.0和2.1之间的兼容性通过头文件sysdep-2.1.h获得,它可以与你自己的模块集成。我选择不把兼容性扩展到1.2避免了给C代码加载太多的条件,而且1.2-2.0的不同已经在前面的章节解释过了。在我将要写完这本书时,我了解到从2.1.43起又引入了一些小的不兼容性;我不打算对之加以评述,因为我不能保证对这些最新版本的完全支持。
注意在本章我不会讲述2.1开发系列引入的所有新东西。我要做的只是移植2.0模块,使之可以在2.0和2.1核心上运行。利用2.1的特征意味着放弃对不具有这些特征的2.0发布的支持。2.0版本仍是本书的重点。在写sysdep-2.1.h时,我已努力使你熟悉新的API,我引入的宏用来使2.1的代码可以在2.0上跑,而不是相反。
本章以重要性逐渐降低的顺序介绍不兼容性;最重要的不同首先被介绍,次要的细节则在后面介绍。
模块化
在Linux社区中,模块化变的越来越重要,开发人员决定用一个更清晰的实现取代旧的。头文件
Changes)。当与旧的核心一起使用时,这个包可以回到兼容模式,因此你可以用这个新包替换modules-2.0.0,即使你经常在2.0和2.1之间切换。
引出符号
符号表的新接口比以前的要容易多了,它依赖于下面的宏:
EXPORT_NO_SYMBOLS;这个宏与register_symtab(NULL)等价;它可以出现在一个函数的内部或外部,因为它只是指导汇编器,而不产生实际代码。如果你想在Linux2.0上编译模块,这个宏应该在init_module中被使用。
EXPORT_SYMTAB;如果你打算引出一些符号,那么模块必须在包含
EXPORT_SYMBOL(name);这个宏表明你想引出这个符号名。它必须在任何函数之外使用。
EXPORT_SYMBOL_NOVERS(name)使用这个宏而不是EXPORT_SYMBOL()强制丢弃版本信息,即使是编译带有版本支持的代码。这对避免一些不必要的重编译很有用。例如,memset函数将总以同样的方式工作;引出符号而不带版本信息允许开发者改变实现(甚至使用的数据类型)而不需insmod标出不兼容性。在模块化的代码中不大可能需要这个宏。
如果这些宏都没有在你的源码中使用,那么所有的非静态符号都被引出;这与在2.0中一如果这些宏都没有在你的源码中使用,那么所有的非静态符号都被引出;这与在2.0中一样。如果这个模块是从几个源文件生成的,你可以从任何源文件引出符号,而且还可以在模块的范围中共享任何符号。如你所看到的,引出符号表的新方法解决了一些问题,但这个创新也引入了一个重要的不兼容性:一个引出了一些符号的模块,如果想同时在2.0和2.1上编译运行,则必须用条件编译来包含两个实现。下面是export模块(v2.1/misc-modules/export.c)如何处理这个问题的当使用2.1.18或更新的核心时,REGISTER_SYMTAB扩展为什么都不做,因为init_module中没有什么需要做的;在函数外使用EXPORT_SYMBOL是引出模块符号唯一需要做的。
核心模块的新的实现利用了ELF二进制格式的特征以获得更好的灵活性。更特别地,当构核心模块的新的实现利用了ELF二进制格式的特征以获得更好的灵活性。更特别地,当构造一个ELF目标文件时,你可以声明除“正文”、“数据”和“bss”之外的节。一个“节”是一个连续的数据区域,与“段”的概念类似。
对于2.1,核心模块必须使用ELF二进制格式编译。事实上,2.1核心利用了ELF的节(见“处理核心空间错误”),只能编译为ELF。因此模块的限制并不是个真正限制。使用ELF允许信息域被存在目标文件中。好奇的读者可以使用objdump –section-headers来观察节头,用objdump –section=.modinfo –full-contents来查看模块特定的信息。实际上,.modinfo一节是用来存储模块信息的节,包含被称做“参数”的值,可以在加载时修改。
当在2.1上编译时,一个参数可以用宏如下声明:MODULE_PARM(variable, type-description);当你在源文件中使用这个宏时,编译器被告知在目标文件中插入一个描述串;这个描述表明variable是个参数,它的类型对应于type-description。insmod和modprobe查看目标文件,保证你被允许修改variable,同时检查参数的实际类型。类型检查对防止不愉快的错误非常重要,例如用一个串覆盖了一个整数,或错把长整数当成了短整数。按我的观点,讲述宏的最好办法时给出几行示例代码。下面的代码属于一个想象的网卡type-description串在头文件
int io[MAX_DEVICES+1]={0,}; MODULE_PARM(io, “1-” __MODULE_STRING(MAX_DEVICES) “i”); 在前一行中,被“字符串化”的值与其他串接在一起构成目标文件中有意义的串。scull示例模块也用MODULE_PARM来声明它的参数(scull_major和其他整数变量)。这在Linux2.0上编译时可能会出问题,那里这个宏未定义。我选择的简单的修正是在sysdep-2.1.h中定义MODULE_PARM,这样在与2.0头文件编译时,它扩展为空语句。其它有意义的值可以象MODULE_AUTHOR()一样 存在模块的.modinfo一节,但它们目前没有使用。请参考
/proc/modules
/proc/modules的格式在2.1.18中略有改变,而所有的模块化代码都被重写了。尽管这个改变并不影响源码,你可能对其细节不感兴趣,因为/proc/modules在模块开发时经常被检查。
新格式和旧的一样是面向行的,每行包含下面的域:
模块名:这个域与Linux2.0相同。
模块大:小这是个十进制数,以字节为单位(而不是内存页)报告长度。这个模块的使用计数如果模块没有使用计数,这个计数报告-1。这是和新的模块化代码一道引入的新特征;你可以写一个模块,它的去除可以有一个函数控制而不是使用计数。这个函数判断模块是否能够被卸载。例如,ipv6模块就使用这个特征。
- 微软官方入门教程19:轻松掌握Vista系统的快
- 微软2008大冲击,预借Vista SP1力促Vista市
- 在收件箱中获得 Windows Vista 的最新更新
- 微软官方Vista入门教程全集19篇(Vista学院
- Windows Vista 的成功将势不可挡
- 快快抛弃Vista,拥抱XP SP3!你觉得呢?
- 浅谈Vista系统关闭虚拟内存与使用内存盘加速
- 嘿嘿,按下键盘上面的三个键,马上让你的Vi
- Windows Vista的盗版率只有Windows XP的一半
- 3DMark和PCMark Vantage新版将只支持Vista系
- Windows外衣Linux心 红旗桌面版详测
- 扮酷你的桌面 Linux超靓壁纸下载(多图)
- Linux安装流程
- 浅谈Linux的内核
- RedHat Linux9.0安装实例(1)
- ARM的嵌入式Linux移植体验之基本概念
- Linux安装要点
- 红旗Linux桌面版5.0BETA版OS
- 如何在大硬盘上安装Linux
- RealPlayer流媒体播放器Linux版
- Linux步入Unix的后尘-铁甲Linux出现
- Linux内核中的同步和互斥分析报告
- Linux操作系统文件系统的桌面应用
- Linux设备驱动编程之定时器
- 嵌入式Linux操作系统启动信息完全注释
- 在Linux操作系统中实现内部进程通信
- Linux大腕警告称开源软件存在安全问题
- Linux下双网卡绑定技术实现负载均衡
- 深入浅出Linux操作系统的优化和微调
- Linux下的中文显示和支持常见问题解答
- 大话G游 专题:手机病毒揭密
- ARP攻击防范与解决方案 路由故障处理手册
- Picasa中文版_Picasa教程 专题:清除流氓软件
- Firefox专题 seo搜索引擎优化专区
- 重装Windows必知的事情 装机之必备软件大行动
