linux 基于 jiffy 的超时
到目前为止所展示的次优化的延时循环通过查看 jiffy 计数器而不告诉任何人来工作. 但是最好的实现一个延时的方法, 如你可能猜想的, 常常是请求内核为你做. 有 2 种方 法来建立一个基于 jiffy 的超时, 依赖于是否你的驱动在等待其他的事件.
如果你的驱动使用一个等待队列来等待某些其他事件, 但是你也想确保它在一个确定时间 段内运行, 可以使用 wait_event_timeout 或者 wait_event_interruptible_timeout:
#include <linux/wait.h>
long wait_event_timeout(wait_queue_head_t q, condition, long timeout); long wait_event_interruptible_timeout(wait_queue_head_t q, condition, long timeout);
这些函数在给定队列上睡眠, 但是它们在超时(以 jiffies 表示)到后返回. 因此, 它们 实现一个限定的睡眠不会一直睡下去. 注意超时值表示要等待的 jiffies 数, 不是一个 绝对时间值. 这个值由一个有符号的数表示, 因为它有时是一个相减运算的结果, 尽管这 些函数如果提供的超时值是负值通过一个 printk 语句抱怨. 如果超时到, 这些函数返回 0; 如果这个进程被其他事件唤醒, 它返回以 jiffies 表示的剩余超时值. 返回值从不会 是负值, 甚至如果延时由于系统负载而比期望的值大.
/proc/jitqueue 文件展示了一个基于 wait_event_interruptible_timeout 的延时, 结 果这个模块没有事件来等待, 并且使用 0 作为一个条件:
wait_queue_head_t wait; init_waitqueue_head (&wait);
wait_event_interruptible_timeout(wait, 0, delay);
当读取 /proc/jitqueue 时, 观察到的行为近乎优化的, 即便在负载下:
phon% dd |
bs=20 count=5 < /proc/jitqueue |
2027024 |
2028024 |
2028025 |
2029025 |
2029026 |
2030026 |
2030027 |
2031027 |
2031028 |
2032028 |
因为读进程当等待超时( 上面是 dd )不在运行队列中, 你看不到表现方面的差别, 无论 代码是否运行在一个抢占内核中.
wait_event_timeout 和 wait_event_interruptible_timeout 被设计为有硬件驱动存在, 这里可以用任何一种方法来恢复执行: 或者有人调用 wake_up 在等待队列上, 或者超时 到. 这不适用于 jitqueue, 因为没人在等待队列上调用 wake_up ( 毕竟, 没有其他代码 知道它 ), 因此这个进程当超时到时一直唤醒. 为适应这个特别的情况, 这里你想延后执 行不等待特定事件, 内核提供了 schedule_timeout 函数, 因此你可以避免声明和使用一 个多余的等待队列头:
163
#include <linux/sched.h>
signed long schedule_timeout(signed long timeout);
这里, timeout 是要延时的 jiffies 数. 返回值是 0 除非这个函数在给定的 timeout 流失前返回(响应一个信号). schedule_timeout 请求调用者首先设置当前的进程状态, 因此一个典型调用看来如此:
set_current_state(TASK_INTERRUPTIBLE); schedule_timeout (delay);
前面的行( 来自 /proc/jitschedto ) 导致进程睡眠直到经过给定的时间. 因为 wait_event_interruptible_timeout 在内部依赖 schedule_timeout, 我们不会费劲显示 jitschedto 返回的数, 因为它们和 jitqueue 的相同. 再一次, 不值得有一个额外的时 间间隔在超时到和你的进程实际被调度来执行之间.
在刚刚展示的例子中, 第一行调用 set_current_state 来设定一些东西以便调度器不会 再次运行当前进程, 直到超时将它置回 TASK_RUNNING 状态. 为获得一个不可中断的延时, 使用 TASK_UNINTERRUPTIBLE 代替. 如果你忘记改变当前进程的状态, 调用 schedule_time 如同调用 shcedule( 即, jitsched 的行为), 建立一个不用的定时器.
如果你想使用这 4 个 jit 文件在不同的系统情况下或者不同的内核, 或者尝试其他的方 式来延后执行, 你可能想配置延时量当加载模块时通过设定延时模块参数.
相关文章
- Linux文件系统(上)
- 使用 Visual Studio 部署 .NET Core 应用 ——.Net Core 部署到SUSE Linux Enterprise Server 12 SP2 64 位(GNOME 版本3.20.2)
- Linux常用命令大全
- [Linux]linux下取消用户名和密码直接登录
- linux分享二:Linux如何修改字符集
- linux(centos8):zabbix配置邮件报警(监控错误日志)(zabbix5.0)
- Linux Ubuntu22.04 docker安装企业微信(docker安装方式,非纯deepin-wine)
- linux 错误码 65280,Android:无法在同一部手机上执行通过Linux部署编译的文件
- 手把手教你从零实现Linux misc设备驱动一(基于友善之臂4412开发板)
- 【Linux】linux经常使用基本命令
- L85.linux命令每日一练 -- 第12章 Linux系统常用内置命令(一)
- L84.linux命令每日一练 -- 第11章 Linux系统管理命令 -- rpm和yum
- L81.linux命令每日一练 -- 第11章 Linux系统管理命令 -- ethtool和mii-tool
- L71.linux命令每日一练 -- 第十章 Linux网络管理命令 -- wget和mailq
- L70.linux命令每日一练 -- 第十章 Linux网络管理命令 -- nc和ssh
- L56.linux命令每日一练 -- 第八章 Linux磁盘与文件系统管理命令 -- swapoff和sync
- L54.linux命令每日一练 -- 第八章 Linux磁盘与文件系统管理命令 -- umount和df
- L34.linux命令每日一练 -- 第五章 Linux信息显示与搜索文件命令 -- echo和watch
- Linux下FTP服务器搭建
- 嵌入式linux开发,Linux下访问PHY芯片寄存器
- 周立功arm linux教程,极速搭建周立功IMX287A ARM Linux开发环境
- Linux【实操篇】—— 用户管理、linux系统root密码找回方式
- Linux下Mysql数据库的基础操作
- 嵌入式Linux开发,Ubuntu下交叉编译内核报错:error while loading shared libraries: /lib/x86_64-linux-gnu/libc++.so: