linux 延后执行
设备驱动常常需要延后一段时间执行一个特定片段的代码,常常允许硬件完成某个任务. 在这一节我们涉及许多不同的技术来获得延后. 每种情况的环境决定了使用哪种技术最好; 我们全都仔细检查它们,并且指出每一个的长处和缺点. ? 一件要考虑的重要的事情是你需要的延时如何与时钟嘀哒比较,考虑到 HZ 的跨各种平台 的范围. 那种可靠地比时钟嘀哒长并且不会受损于它的粗粒度的延时,可以利用系统时钟. 每个短延时典型地必须使用软件循环来实现. 在这 2 种情况中存在一个灰色地带. 在本 章,我们使用短语" long " 延时来指一个多 jiffy 延时,在一些平台上它可以如同几个 毫秒一样少,但是在 CPU 和内核看来仍然是长的. ? 下面的几节讨论不同的延时,通过采用一些长路径,从各种直觉上不适合的方法到正确的 方法. 我们选择这个途径因为它允许对内核相关定时方面的更深入的讨论. 如果你急于找 出正确的代码,只要快速浏览本节. ? 长延时? 偶尔地,一个驱动需要延后执行相对长时间 -- 多于一个时钟嘀哒. 有几个方法实现这类 延时; 我们从最简单的技术开始,接着进入到高级些的技术. ? 忙等待 ? 如果你想延时执行多个时钟嘀哒,允许在值中某些疏忽,最容易的( 尽管不推荐 ) 的实 现是一个监视 jiffy 计数器的循环. 这种忙等待实现常常看来象下面的代码,这里 j1 是 jiffies 的在延时超时的值: ? while (time_before(jiffies,j1)) cpu_relax(); ? 对 cpu_relex 的调用使用了一个特定于体系的方式来说,你此时没有在用处理器做事情. 在许多系统中它根本不做任何事; 在对称多线程(" 超线程" ) 系统中,可能让出核心给 其他线程. 在如何情况下,无论何时有可能,这个方法应当明确地避免. 我们展示它是因 为偶尔你可能想运行这个代码来更好理解其他代码的内幕. ? 我们来看一下这个代码如何工作. 这个循环被保证能工作因为 jiffies 被内核头文件声 明做易失性的,并且因此,在任何时候 C 代码寻址它时都从内存中获取. 尽管技术上正 确( 它如同设计的一样工作 ),这种忙等待严重地降低了系统性能. 如果你不配置你的内 核为抢占操作,这个循环在延时期间完全锁住了处理器; 调度器永远不会抢占一个在内核 中运行的进程,并且计算机看起来完全死掉直到时间 j1 到时. 这个问题如果你运行一个 可抢占的内核时会改善一点,因为,除非这个代码正持有一个锁,处理器的一些时间可以 被其他用途获得. 但是,忙等待在可抢占系统中仍然是昂贵的. ? 更坏的是,当你进入循环时如果中断碰巧被禁止,jiffies 将不会被更新,并且 while 条件永远保持真. 运行一个抢占的内核也不会有帮助,并且你将被迫去击打大红按钮. ? ? 这个延时代码的实现可拿到,如同下列的,在 jit 模块中. 模块创建的这些 /proc/jit* 文件每次你读取一行文本就延时一整秒,并且这些行保证是每个 20 字节. 如果你想测试 忙等待代码,你可以读取 /proc/jitbusy,每当它返回一行它忙-循环一秒. ? 为确保读,最多,一行( 或者几行 ) 一次从 /proc/jitbusy. 简化的注册 /proc 文件的 内核机制反复调用 read 方法来填充用户请求的数据缓存. 因此,一个命令,例如 cat /proc/jitbusy,如果它一次读取 4KB,会冻住计算机 205 秒. ? 推荐的读 /proc/jitbusy 的命令是 dd bs=200 < /proc/jitbusy,可选地同时指定块数 目. 文件返回的每 20-字节 的行表示 jiffy 计数器已有的值,在延时之前和延时之后. 这是一个例子运行在一个其他方面无负担的计算机上: ?
? 看来都挺好: 延时精确地是 1 秒 ( 1000 jiffies ),并且下一个 read 系统调用在上一 个结束后立刻开始. 但是让我们看看在一个有大量 CPU-密集型进程在运行(并且是非抢占 内核)的系统上会发生什么: ?
? 这里,每个 read 系统调用精确地延时 1 秒,但是内核耗费多过 5 秒在调度 dd 进程以 便它可以发出下一个系统调用之前. 在一个多任务系统就期望是这样; CPU 时间在所有运 行的进程间共享,并且一个 CPU-密集型 进程有它的动态减少的优先级. ( 调度策略的讨 论在本书范围之外). ? 上面所示的在负载下的测试已经在运行 load50 例子程序中进行了. 这个程序派生出许多 什么都不做的进程,但是以一种 CPU-密集的方式来做. 这个程序是伴随本书的例子文件 的一部分,并且缺省是派生 50 个进程,尽管这个数字可以在命令行指定. 在本章,以及 在本书其他部分,使用一个有负载的系统的测试已经用 load50 在一个其他方面空闲的计 算机上运行来进行了. ? 如果你在运行一个可抢占内核时重复这个命令,你会发现没有显著差别在一个其他方面空 闲的 CPU 上以及下面的在负载下的行为: ? phon% dd bs=20 count=5 < /proc/jitbusy 14940680 14942777 14942778 14945430 ? ? ?
? 这里,没有显著的延时在一个系统调用的末尾和下一个的开始之间,但是单独的延时远远 比 1 秒长: 直到 3.8 秒在展示的例子中并且随时间上升. 这些值显示了进程在它的延时 当中被中断,调度其他的进程. 系统调用之间的间隙不是唯一的这个进程的调度选项,因 此没有特别的延时在那里可以看到. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |