HZ和jiffies

内核通过定时器中断来跟踪时间流。时钟中断由系统定时器一周期性的间隔产生,这个间隔有内核根据HZ的值决定。HZ是一个与体系结构有关的常数,定义在<linux/param.h>或者该文件包含的某个子平台的相关文件中。HZ是用来定义每一秒中有多少次时钟中断。例如HZ为1000,代码每秒产生1000次时钟中断。
全局变量jiffies用于记录系统启动以来产生的节拍的总数,一个节拍代表多长时间,与HZ大小有关,例如HZ = 200,则一个jiffies对应5ms(1s = 1000ms,1000ms / 200 = 5ms)时间。比较两个节点的宏如下,包含头文件<linux/jiffies.h>
int time_after(unsigned long a, unsigned long b); b > a 时返回真
int time_before(unsigned long a, unsigned long b); b < a 时返回真
int time_after_eq(unsigned long a, unsigned long b); b >= a 时返回真
int time_before_eq(unsigned long a, unsigned long b); b <= a 时返回真
计算两个jiffies实例之间的差:diff = (long)t2 - (long)t1;
将差值转换为毫秒值:msec = diff * 1000 / HZ;

获取当前时间

获取时间的函数原型如下:

#include <linux/time.h>struct timeval {time_t tv_sec; /* seconds */suseconds_t tv_usec; /* microseconds */
};
void do_gettimeofday(struct timeval *tv);struct timespec {time_t tv_sec; // seconds long tv_nsec; // and nanoseconds
};
struct timespec current_kernel_time(void);

延迟执行

长延迟
#include <linux/sched.h>
signed long schedule_timeout(signed long timeout);
timeout是用jiffies表示的延迟时间,正常值返回0.
schedule_timeout在使用前需要设置当前进程状态。

set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(2*HZ); /* 睡2秒 */
第一行调用set_current_state已设置当前进程状态,调度器只有在超时到期且其状态为TASK_RUNNING时才会运行这个进程。如果不希望被用户空间打断,可以将进程状态设置为TASK_UNINTERRUPTIBLE。

短延迟
如果需要处理涉及到几十个毫秒级别的延迟,可以使用下面的函数进行处理。
#include <Linux/delay.h>
void ndelay(unsigned long nsecs); 延迟纳秒
void udelay(unsigned long usecs); 延迟微秒
void mdelay(unsigned long msecs); 延迟毫秒
注意:这个三个延迟函数都是忙等待函数,因而在延迟的过程中无法运行其他任务。实现毫秒级(或者更长)延迟还有一个不涉及忙等待的方法,包含头文件<Linux/delay.h>,具体如下:
void msleep(unsigned int millisecs); 休眠毫秒
void ssleep(unsigned int seconds); 休眠秒
unsigned long msleep_interruptible(unsigned int millisecs); 休眠毫秒,中断可以唤醒

工作队列

工作队列有struct workqueue_struct的类型,该结构定义在<linux/workqueue.h>中。在使用之前,我们必须显示的创建一个工作队列,可使用下面两个函数:
struct workqueue_struct *create_wrokqueue(const char *name);
struct workqueue_struct *create_singlethread_workqueue(const char *name);
每个工作队列有一个或多个专用的进程(“内核线程”),这些进程运行提交到该队列的函数。如果我们使用create_workqueue,则内核会在系统中的每个处理器上为该工作队列创建专用的线程。在许多情况下,众多的线程可能对性能具有某种程度的杀伤力;因此,如果单个工作线程足够使用,那么应该使用create_singlethread_workqueue创建工作队列。

要向一个工作队列提交一个任务,需要填充一个work_struct结构,可以通过下面的宏在编译时完成:
DECLARE_WORK(name, void (*function)(void *), void *data);
其中name是要声明的结构名称,function是要从工作队列中调用的函数,data是传递给该函数的值。
如果需要运行时构造work_struct结构,使用下面的宏:
INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work, void (*function)(void *), void *data);
INIT_WORK完成更加彻底的结构初始化工作;在首次构造该结构时,应该使用这个宏。如果work_struct结构已经提交到工作队列,只是需要修改该结构,则应该使用PREPARE_WORK。

将工作提交到工作队列,可以使用下面的两个函数之一:
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);
他们都是将work添加到指定的queue。queue_delayed_work会在经过指定的jiffies(由delay指定)之后才会被执行。如果工作被成功添加到队列,上述函数返回1,。返回值为非0值表示给定的work_struct结构已经在等待队列中,不能再次加入。
结束使用工作队列后,释放资源使用:void destroy_workqueue(struct workqueue_struct *queue);

共享队列

在许多情况下,设备驱动程序不需要有自己的工作队列。如果我们只是偶尔需要向队列中提交任务,有一种更简单、更有效的方法就是使用内核提供的共享的默认工作队列。但是使用的时候要注意,因为是与其他人共享该工作队列,所以我们不应该长期占用该队列,即不能长时间休眠。并且我们的任务可能需要更长的时间才能获得处理器时间
添加工作的方法是:
int schedule_work(struct work_struct *work);
带延迟的版本:
int schedule_delayed_work(struct work_struct *work, unsigned long delay);
我们在创建一个简单的字符设备代码的基础上添加一个共享队列用作测试。通过ioctl来触发添加工作schedule_work。示例代码如下:

static struct work_struct work;static void notification_work(struct work_struct *work)
{pr_info("%s\n", __func__);
}static long csdn_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{/* ohters code */switch (cmd){case CSDN_IOC_GET:pr_info("CSDN_IOC_GET \n");schedule_work(&work);break;/* ohters code */}/* ohters code */
}static __init int csdn_init(void)
{/* ohters code */INIT_WORK(&work, notification_work);/* ohters code */
}

打印结果如下:
[ 6164.910398] csdn_ioctl
[ 6164.910399] CSDN_IOC_GET
[ 6164.920519] notification_work

时间、延迟以及延缓操作相关推荐

  1. 【Linux 驱动】第七章 时间 延迟及延缓操作

    一,度量时间差 时钟中断由系统定时硬件以周期性的间隔产生,这个间隔由内核根据 HZ 值来设定,HZ 是一个体系依赖的值,在 <linux/param.h>中定义或该文件包含的某个子平台相关 ...

  2. linux设备驱动七(时间、延迟及延缓操作)

    知识点: 如何度量时间差,如何比较时间 如何获得当前时间 如何将操作延迟指定一段时间 如何调度异步函数到指定时间之后执行 度量时间差 HZ指一秒内产生的时钟中断次数,即时钟中断频率 jiffies_6 ...

  3. 《Linux Device Driver》——时间、延迟及延缓操作

    任务: 度量时间差,如何比较时间 获得当前时间 将操作延迟指定一段时间 调度异步函数到指定时间之后执行 度量时间差 内核通过定时器中断来跟踪时间流. 时间中断由系统定时硬件以周期性的间隔产生,这个间隔 ...

  4. 时间、延迟及延缓操作

    现实中的设备驱动程序除了必需的操作之外还要做更多工作,如定时.内存管理.硬件访问等,现在来看看内核是如何对时间进行处理的. 关于时钟的一些说明:一台装有操作系统的计算机里一般有两个时间:硬件时钟和软件 ...

  5. Linux设备驱动程序学习(10)-时间、延迟及延缓操作(Jiq.c)

    共享隊列 点击(此处)折叠或打开 /* * jiq.c -- the just-in-queue module * * Copyright (C) 2001 Alessandro Rubini and ...

  6. 数据库归档及热点库_postgresql连续归档及时间点恢复的操作

    postgresql连续归档及时间点恢复的操作,备份,日志,时间,目录,文件 postgresql连续归档及时间点恢复的操作 易采站长站,站长之家为您整理了postgresql连续归档及时间点恢复的操 ...

  7. python 表格格式输出_利用python对excel中一列的时间数据更改格式操作

    问题场景:需要将下列的交期一列的数据格式更改成2019/05/10 存货编码 尺寸 数量 交期 0 K10Y0190000X B140 200 2019-05-10 00:00:00 1 K10Y01 ...

  8. sql server2005 无法修改表,超时时间已到 在操作完成之前超时时

    在sql server2005 中,在修改表时,保存的时候显示:无法修改表,超时时间已到 在操作完成之前超时时间已过或服务器未响应  这是执行时间设置过短的原因,可以修改一下设置便能把执行时间加长,以 ...

  9. C标准函数库中获取时间与日期、对时间与日期数据操作及格式化

    表示时间的三种数据类型[编辑] 日历时间(calendar time),是从一个标准时间点(epoch)到现在的时间经过的秒数,不包括插入闰秒对时间的调整.开始计时的标准时间点,各种编译器一般使用19 ...

最新文章

  1. Windows 7 SDK Fails to Install with Return Code 5100 (GRMSDK_EN_DVD.iso)
  2. reshape2 数据操作 数据融合( cast)
  3. 蒙特卡罗方法验证凯利公式
  4. Fedora中允许mysql远程访问的几种方式
  5. 实验7.3 字符串 7-8 删除重复字符
  6. c 提示错误expected) before ; token_实践总结——Git 常见错误及解决方法
  7. 导出FLASH用反射的时候要注意的问题
  8. 蔡勒公式(计算星期几)
  9. java 操作 led_Java中使用反射机制操作LED
  10. 百度 图像识别Api logo识别 基于java的Demo
  11. RTCP 协议的 NACK 报文
  12. linux字体不识别不了怎么办,Docker容器不识别宋体等字体怎么办
  13. IBM Tivoli NetView网管软件实战
  14. 彻底了解DVD:从入门到精通(二)[转]
  15. 【转载】一个硕士程序员的求婚日记——做开发的不是木头人!
  16. Python中for循环的使用
  17. 淘宝api例子 通过宝贝地址取宝贝标题价格图片
  18. Java环境的下载和配置
  19. 测试酒的真假软件,茅台防伪溯源系统软件
  20. BUUCTF Misc [BJDCTF2020]鸡你太美 [BJDCTF2020]一叶障目 [SWPU2019]神奇的二维码 梅花香之苦寒来 [BJDCTF2020]纳尼

热门文章

  1. 题目:什么是内联函数
  2. 如何批量重命名文件?
  3. 破解Excel保护密码
  4. 管程法实现生产者消费者问题
  5. 2021年计算机类 人工智能 软件SCI一区期刊
  6. MYSQL 基础篇 | 02-MYSQL基础应用
  7. jqGrid简单使用、json格式和jsonReader介绍
  8. 企企通:企业供应商风险管理,如何用采购管理软件赋能?
  9. python 开启子进程的两种方式
  10. python安装包问题小结