| 内存,那么就可以用预分配的池。
系统使用 mempool_destroy() 来回收内存池。
除了为内存分配引入了内存池之外,2.5内核还引入了三个用于常规内存分配的新的GFP标记,它们是:
__GFP_REPEAT -- 告诉页分配器尽力去分配内存。如果内存分配失败过多,应该减少这个标记的使用。
__GFP_NOFAIL -- 不能出现内存分配失败。这样,由于调用者被转入休眠状态,可能需要一段比较长的时间才能完成分配,调用者的需求才能得到满足。
__GFP_NORETRY -- 保证分配失败后不再重试,而向调用者报告失败状态。
除了内存分配的变化以外,remap_page_range()调用——用来映射页到用户空间——也经过了少量修改。相对于2.4来说,现在它多了一个参数。虚拟内存区域(VMA)指针要作为第一个参数,然后是四个常用的参数(start,end,size 和 protection 标记)。
工作队列接口 工作队列接口是在2.5的开发过程中引入的,用于取代任务队列接口(用于调度内核任务)。每个工作队列有一个专门的线程,所有来自运行队列的任务在进程的上下文中运行(这样它们可以休眠)。驱动程序可以创建并使用它们自己的工作队列,或者使用内核的一个工作队列。工作队列用以下方式创建: struct workqueue_struct *create_workqueue(const char *name);
在这里 name 是工作队列的名字。
工作队列任务可以在编译时或者运行时创建。任务需要封装为一个叫做 work_struct 的结构体。在编译期初始化一个工作队列任务时要用到: DECLARE_WORK(name, void (*function)(void *), void *data);
在这里 name 是 work_struct 的名字,function 是当任务被调度时调用的函数,data 是指向那个函数的指针。
在运行期初始化一个工作队列时要用到: INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
用下面的函数调用来把一个作业(一个类型为work_struct 结构的工作队列作业/任务)加入到工作队列中: int queue_work(struct workqueue_struct *queue, struct work_struct *work); int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work, unsigned long delay);
在queue_delay_work()中指定 delay,是为了保证至少在经过一段给定的最小延迟时间以后,工作队列中的任务才可以真正执行。
工作队列中的任务由相关的工作线程执行,可能是在一个无法预期的时间(取决于负载,中断等等),或者是在一段延迟以后。任何一个在工作队列中等待了无限长的时间也没有运行的任务可以用下面的方法取消: int cancel_delayed_work(struct work_struct *work);
如果当一个取消操作的调用返回时,任务正在执行中,那么这个任务将继续执行下去,但不会再加入到队列中。清空工作队列中的所有任务使用: void flush_workqueue(struct workqueue_struct *queue);
销毁工作队列使用: void destroy_workqueue(struct workqueue_struct *queue);
不是所有的驱动程序都必须有自己的工作队列。驱动程序可以使用内核提供的缺省工作队列。由于这个工作队列由很多驱动程序共享,任务可能会需要比较长一段时间才能开始执行。为了解决这一问题,工作函数中的延迟应该保持最小或者干脆不要。
需要特别注意的是缺省队列对所有驱动程序来说都是可用的,但是只有经过GP许可的驱动程序可以用自定义的工作队列:
int schedule_work(struct work_struct *work); -- 向工作队列中添加一个任务
int schedule_delayed_work(struct work_struct *work, unsigned long delay); -- 向工作队列中添加一个任务并延迟执行
当模块被缷载时应该去调用一个 flash_scheduled_work() 函数,这个函数会使等待队列中所有的任务都被执行。
中断例程的变化 2.5的中断处理程序内部已经经历了许多变化,但是绝大部分对于普通的驱动程序开发者来说没有影响。不过,还是有一些重要的变化会影响到驱动程序开发者。
现在的中断处理函数的返回代码是一个 irqreturn_t 类型。这个由 Linus 引入的变化意味着中断处理程序告诉通用的 IRQ 层是否真的要中断。这样做是为了当中断请求不断到来时(原因是驱动程序偶然激活了一个中断位或者硬件坏掉了),捕获假中断(尤其是在共享的PCI线上),而任何驱动程序对此都是无能为力的。在2.6中,驱动程序如果要从一个设备上发出一个中断需要返回 IRQ_HANDLED,如果不是的话返回 IRQ_NONE。这样可以帮助内核的 IRQ 层清楚地识别出哪个驱动程序正在处理那个特定的中断。如果一个中断请求不断到来而且没有注册那个设备的处理程序(例如,所有的驱动程序都返回 IRQ_NONE),内核就会忽略来自那个设备的中断。缺省情况下,驱动程序 IRQ 例程应该返回 IRQ_HANDLED,当驱动程序正在处理那个中断时却返回了 IRQ_NONE,说明存在 bug。新的中断处理程序可能是类似于这样:
清单 4. 2.6的中断处理程序伪代码
irqreturn_t irq_handler(...) {
..
if (!(my_interrupt)
return IRQ_NONE; // not our interrupt
...
return IRQ_HANDLED; // return by default
}
注意,cli(),sti(),save_flags()和 restor_flags() 是不赞成使用的方法。取而代之的是 local_save_flags() 和 local_irq_disable(),用来禁止所有的本地中断(本处理器内的)。禁止所有处理器的中断是不可能的。
统一的设备模型 2.5开发过程中另一个最值得关注的变化是创建了一个统一的设备模型。这个设备模型通过维持大量的数据结构囊括了几乎所有的设备结构和系统。这样做的好处是,可以改进设备的电源管理和简化设备相关的任务管理,包括对以下信息的追踪:
- 系统中存在的设备,其所连接的总线
- 特定情形下设备的电源状态
- 系统清楚设备的驱动程序,并清楚哪些设备受其控制
- 系统的总线结构:哪个设备连接在哪个总线上,以及哪些总线互连(例如,USB和PCI总线的互连)
- 设备在系统中的类别描述(类别包括磁盘,分区等等)
在2.5内核中,与设备驱动程序相关的其他发展包括:
- 不再使用 malloc.h。所有包含 <linux/malloc.h>(用于内存分配)的代码现在要替换为 <linux/slab.h>。
- 用于 x86 体系结构的 HZ 值增加到1000。引入了一个叫做 jiffies_64 的瞬间计算器,以避免由于 HZ 值的变化而引起瞬间变量的迅速溢出。
- 引入了一个叫做 ndelay() 的新的延迟函数,允许纳秒级的等待。
- 引入了一个叫做 seqlock() 的新类型的锁,用于锁定小段的经常被访问的数据(不是指针)。
- 由于2.6内核可以抢占,应该在驱动程序中使用 preempt_disable() 和 preempt_enable(),从而保护代码段不被抢占(禁止 IRQ 同时也就隐式地禁止了抢占)。
- 在2.5中加入了异步 I/O。这意味着用户进程可以同时进行多个 I/O 操作,而不用等待它们完成。在字符驱动程序中引入了异步 API。
- 块层在2.5的开发过程中经历了大幅度的变化。这意味着原来用于2.4的块设备需要进行重新设计。
- 在2.5中引入了sys文件系统,它给出了系统的设备模型的用户空间描述。它挂载在 /sys 目录下。
结束语 由于相对于2.4来说 Linux2.6发生了太多的变化,所以在 Linux 内核界有一种说法是新的发布版本应该命名为3.0。Linus 将最终决定如何命名,官方可能将于2003年11月发布官方版本。不管最终采用哪个版本号,相对于2.4来说,新的内核发布版本在多种平台和体系结构上性能将更快,可扩展性更强,更加稳定。
Linus 已经邀请世界各地的测试人员来查找 bug 和报告问题,并要求发行者提供2.6版本的下载。如果您想参加,您可以在下面的参考资料中找到下载和安装的链接。
参考资料
- 阅读来自 KernelTrap 的如何升级到2.6内核。
- Joseph Pranevich 的 Linux 2.6的精彩世界更深入全面地介绍了2.6内核对嵌入式、大型的和多处理器支持,以及新内核的联网和安全特性,是一篇很好的读物。
- Dave Jones 提供的2.6 - 期待的是什么也对2.6中的特性和变化做了展望。
- 我们将来使用 Linux 2.6 还是 Linux 3.0? 请看内核邮件列表上的讨论。
- Kerneltraffic 根据内核邮件列表对每周亮点做了报导。
- 每日和每周的关于内核方面的报导和列表可以在 Linux 每周新闻 (专门的内核新闻有自己的页面)找到。
- 在 kernelnewbies上查阅 当前内核情况。
- 查阅 Rik van Riel 的面向内核新手的站点。
- 不要错过必读的 Linux 每周新闻的关于2.5驱动程序移植的文章。
- 想要更多地了解O(1)调度器吗?请访问 Ingo Molnar的页面。
- Robert Love的一套 调度器相关的工具 叫做 schedutils。
- 了解 Native Posix Threading Library design (PDF格式).
- 获得 Rik van Riel 提供的 r-map 补丁。
- 为了加载和缷载新编译的模块,您将需要一组新的模块工具,从 kernel.org 网站可以得到。
- Bert Hubert has 编辑了 关于 futexes 的文档 以及 HOWTO on IPSec。
- 熟悉新的 Linux 音频工具,请访问 Advanced Linux Sound Architecture (ALSA) 网站。
- Linux 每周新闻有 关于工作队列的文章。
- IBM developerWorks 专稿 在嵌入式设备上的 Linux 系统开发 由 Anand K Santhanam 和 Vishal Kulkarni 共同撰写。
- 其他相关的 developerWorks 文章,请访问:
- 在嵌入式设备上的 Linux 系统开发
- 嵌入式 Linux 应用程序:概述
- 接触 2.4 内核
- 编译 Linux 内核
- 在developerWorks Linux 专区可以找到更多 为Linux 开发人员准备的资料。
关于作者 Anand K Santhanam 在印度的 Madras 大学获得计算机科学工学学士学位。自 1999 年 7 月以来,他一直在印度的 IBM Global Services(软件实验室)工作。他是 IBM Linux 小组的成员,这个小组主要致力于嵌入式系统中的 ARM-Linux、设备驱动程序和电源管理的研究和开发。他感兴趣的其他领域是 OS 内部和联网。可以通过 asanthan@in.ibm.com 与他联系。
上一页 [1] [2] |