
详解Linux操作系统设备驱动兼容性
发布时间:2006-10-13 12:22:18 来源:天极博客 网友评论 0 条访问用户空间的新的函数集初看起来可能有点令人失望,但它们的确使程序员的日子好过的多了。在Linux2.1上,不再需要显式地检查用户空间;access_ok一般不需要调用。使用新接口的代码可以直接进行数据传送。_ret函数在实现系统调用时证明是相当有用的,因为一个用户空间的失败通常导致系统调用的一个返回-EFAULT的失败。因此,一个典型的read实现,看起来如下:
long new_read(struct inode *inode, struct file *filp, char *buf, unsigned long count); {
/* identify your data (device-specific code) *
/ if (__copy_to_user(buf, new_data, count)) return -EFAULT; return count; }注意使用不进行检查的__copy_to_user是因为调用者在把数据传输分派到文件操作之前已经检查了用户空间。这就象2.0,read和write不需要调用verify_area。类似地,典型的ioctl实现看起来如下:
int new_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); { /
* device-specific checks, if needed
*/ switch(cmd){ case NEW_GETVALUE: put_user_ret(new_value, (int *)arg, -EFAULT);
break; case NEW_SETVALUE: get_user_ret(new_value, (int *)arg, -EFAULT);
default: return –EINVAL; } return 0; }版本2.0的对应者不同的是,这个函数在switch语句之前并不需要检查参数,因为每个get_user或put_user会进行检查。另一方面,当你想写可以同时在2.0和2.1上编译的代码时,问题变得稍微复杂一些,因为在老的核心上,你不能用C预处理器伪装新的行为。你不能简单地#define一个接收两个参数的get_user宏,因为实际的get_user实现在2.0中已经是个宏。我在写既可移植有高效率的代码的选择是设置sysdep-2.1.h以提供具有下列函数的源码。下面只列出了读取数据的函数;写数据的函数行为完全一样。
int access_ok(type, address, size);当在2.0上编译时,这个函数以verify_area的名义实现。int verify_area_20(type, address, size);通常,当为Linux2.1写代码时,你不需调用access_ok。另一方面,当在Linux2.0上编译时,必须调用verify_area。这个函数就是要填平这个不同:当为Linux2.1编译时,它扩展为空;而为2.0编译时,它扩展为原来的verify_area。这个函数不能被称做verify_area,因为2.1已经有一个宏叫这个名字了。在2.1中定义的verify_area宏实现了access_ok的老的语义,它的存在是为了简化源码从2.0到2.1的转换。(从理论上说,你可以在你的模块中留下verify_area,只是将函数名改一下;这种简单移植技巧的缺点是新版本不能在2.0上编译。)
int GET_USER(var, add); int __GET_USER(var, add); GET_USER_RET(var, add, ret);当在2.1上编译时,这些宏扩展为实际的get_user函数,即上面解释过的那些。当在2.0上编译时,get_user的2.0实现被用来实现与2.1中同样的功能。
int copy_from_user(to, from, size)
; int copy_from_user(to, from, size)
; int __copy_from_user(to, from, size)
; copy_from_user_ret(to, from, size);当在2.0上编译时,这些扩展为memcpy_fromfs;而在2.1上,则使用本身的函数。_ret一类在2.0上从不会返回,因为复制函数不会失败。
我个人比较喜欢这种实现兼容性的方法,但这并不是唯一的方法。在我的示例代码中,任何用户空间的访问(除了用来read或write的缓冲区,它们已经事先检查过了)之前,verify_area_20必须被调用。另一种方法更加忠实于2.1的语义,即当用2.0时,在每个get_user 和copy_from_user之前自动生成一个verify_area。这个选择在源码级要更清晰一些,但在版本2.0上编译时效率相当低,包括代码大小和执行时间。可以同时在2.0和2.1上编译的示例代码,如scull模块,可以在目录v2.1/scull中找到。我不觉得这个代码足够有趣,因此不在这里给出。
任务队列
从2.1.30开始的Linux版本不再定义函数queue_task_irq和queue_task_irq_off,因为在queue_task上的实际加速不值得花精力维护两个独立的函数。当新机制被加到核心时,这就变得明显了。在源码级,这是2.0和2.1之间唯一的区别;头文件定义了消失的函数简化了从2.0移植驱动程序。感兴趣的读者可以查看
- 微软官方入门教程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必知的事情 装机之必备软件大行动
