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 计数器已有的值, 在延时之前和延时之后. 这是一个例子运行在一个其他方面无负担的计算机上:
phon% dd |
bs=20 count=5 < /proc/jitbusy |
1686518 |
1687518 |
1687519 |
1688519 |
1688520 |
1689520 |
1689520 |
1690520 |
1690521 |
1691521 |
看来都挺好: 延时精确地是 1 秒 ( 1000 jiffies ), 并且下一个 read 系统调用在上一 个结束后立刻开始. 但是让我们看看在一个有大量 CPU-密集型进程在运行(并且是非抢占 内核)的系统上会发生什么:
phon% dd |
bs=20 count=5 < /proc/jitbusy |
1911226 |
1912226 |
1913323 |
1914323 |
1919529 |
1920529 |
1925632 |
1926632 |
1931835 |
1932835 |
这里, 每个 read 系统调用精确地延时 1 秒, 但是内核耗费多过 5 秒在调度 dd 进程以 便它可以发出下一个系统调用之前. 在一个多任务系统就期望是这样; CPU 时间在所有运 行的进程间共享, 并且一个 CPU-密集型 进程有它的动态减少的优先级. ( 调度策略的讨 论在本书范围之外).
上面所示的在负载下的测试已经在运行 load50 例子程序中进行了. 这个程序派生出许多 什么都不做的进程, 但是以一种 CPU-密集的方式来做. 这个程序是伴随本书的例子文件 的一部分, 并且缺省是派生 50 个进程, 尽管这个数字可以在命令行指定. 在本章, 以及 在本书其他部分, 使用一个有负载的系统的测试已经用 load50 在一个其他方面空闲的计 算机上运行来进行了.
如果你在运行一个可抢占内核时重复这个命令, 你会发现没有显著差别在一个其他方面空 闲的 CPU 上以及下面的在负载下的行为:
phon% dd bs=20 count=5 < /proc/jitbusy 14940680 14942777
14942778 14945430
14945431 |
14948491 |
14948492 |
14951960 |
14951961 |
14955840 |
这里, 没有显著的延时在一个系统调用的末尾和下一个的开始之间, 但是单独的延时远远 比 1 秒长: 直到 3.8 秒在展示的例子中并且随时间上升. 这些值显示了进程在它的延时 当中被中断, 调度其他的进程. 系统调用之间的间隙不是唯一的这个进程的调度选项, 因 此没有特别的延时在那里可以看到.
相关文章
- nagios安装check_linux_stats.pl插件报错Can't locate Sys/Statistics/Linux.pm in @INC的处理?
- wkhtmltopdf:一个 Linux 中将网页转成 PDF 的智能工具
- 如何在 Arch Linux 的终端里设定 WiFi 网络
- 如何使用 pv 命令监控 linux 命令的执行进度
- [转]linux下的CPU压力测试工具与方法介绍
- ubuntu 18.04上执行buildman安装了交叉工具链之后编译报错"aarch64-linux/7.3.0/cc1: error while loading shared libraries: libmpfr.so.4: cannot open shared object file: No such file or directory"如何处理?
- Linux - ps aux ,more,less,head,tail,head和tail的高级用法,使用tail 动态监控某个文件的变化
- linux mysql 执行报错
- Linux执行shell脚本的方法
- 《高性能Linux服务器构建实战:系统安全、故障排查、自动化运维与集群架构》——1.6 服务器遭受攻击后的处理过程
- 深入理解Linux网络技术内幕(十一)——帧的传输
- 获取系统开机的时间(Windows、Linux)
- linux 使用jar 打包成war
- Linux中设置服务自启动的三种方式
- Linux基础:系统启动过程(5个阶段)、linux关机正确流程及常用实例命令、linux目录结构(常见目录解释及目录的分类介绍)
- Linux使用fuser命令找出访问文件系统的进程
- 【Linux篇<Day01>】——Linux基本常识、常用指令【上】
- 【正点原子Linux连载】第十三章 多媒体 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
- Linux学习笔记(25)linux批量管理
- Linux学习笔记(20)linux exec
- Linux学习笔记(9)linux网络管理与配置之一——Linux基础网络命令与学习大纲(0)
- linux下无法执行PHP命令,错误 php: command not found
- linux建立软链接