时间、延迟及延缓操作(第七章 )

1、使用jiffies计数器
     需包含头文件<linux/jiffies.h>( 注:在本人测试的时候系统找不到该头文件,不知道是不是本书的错误之处,在linux系统编程中Robert Love 这样注明的: The Linux kernel now supports “tickless” operation, so this is no longer strictly true.
2、处理器特定的寄存器
     (1)需包含头文件<asm/msr.h>(x86专用的头文件)
     rdtsc(low32, high32);
     rdtscl(low32);
     rdtscll(var64);
     (2)其他平台也提供了一个与平台无关的功能,在<asm/timex.h>(由<linux/timex.h>包含),其原型如下:
     #include <linux/timex.h>
     cycles_t get_cycles(void);
3、获取当前时间
     将墙钟时间转换为jiffies值的函数:
     unsigned long mktime(unsigned int year, unsigned int mon, unsigned int day,
                                     unsigned int hour, unsigned int min, unsigned int sec);
4、延迟执行
(1)长延迟
     1)忙等待( 注:最好不用)
     while (time_before(jiffies, ji))
          cpu_relax();
     2)让出处理器
     #include <linux/sched.h>
     while (time_before(jiffies, ji)){
          schedule();
     }
     3)超时
      如果驱动程序受用等待队列来等待其他一些时间,而我们同时希望在特定时间段中运行,怎可以使用:
     #include <linux/wait.h>
     long wait_event_timeout(wait_queue_head_t a, condition, long timeout);
     或
     long wait_queue_interruptible_timeout(wait_queue_head_t q, condition, long timeout);
     不等待特定事件的延迟,内核为我们提供了:
     #include <linux/sched.h>
     singed long schedule_timeout(signed long timeout);
(2)短延迟
     #include <linux/delay.h>         //这些函数实际包含在<asm/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);
     unsigned long msleep_interruptiable(unsigned int maillisecs);
     void ssleep(unsigned int seconds);
5、定时器API
     内核为驱动程序提供了一组用来声明、注册和删除内核定时器的函数。
     #include <linux/timer.h>
     struct timer_list {
          /*......*/
          unsigned long expires;
          void (*function) (unsigned long);
          unsigned long data;
     };
     
     void init_timer(struct timer_list * timer);
     struct timer_list TIMER_INITIALIZER(_function, _expires, _data);

     void add_timer(struct timer_list * timer);
     int del_timer(struct timer_lsit * timer);

      其他几个内核定时器API:
     int mod_timer(struct timer_list *timer, unsigned long expires);
     int del_timer_sync(struct timer_list *timer);
     int timer_pending(const struct timer_list *timer);
6、内核定时器的实现
7、tasklet
     #include  <linux/interrupt.h>
     struct tasklet_struct {
          /*......*/
          void (*func) (unsigned long);
          unsigned long data;
     };
     
     void tasklet_init(struct tasklet_struct *t, void (*func) (unsigned long), unsigned long data);
     DECLARE_TASKLET(name, func, data);
     DECLARE_DISABLED(name, func, data);
tasklet相关内核接口:
     void tasklet_disable(struct tasklet_struct *t);
     void tasklet_disable_nosync(struct tasklet_struct *t);
     void tasklet_enalbe(struct tasklet_struct *t);
     void tasklet_schedule(struct tasklet_struct *t);
     void tasklet_hi_schedule(struct tasklet_struct *t);
     void tasklet_kill(struct tasklet_struct *t);
8、工作队列
注:工作队列与tasklet的关键区别:tasklet会在很短的时间内很快执行,并且以原子模式执行,而工作队列函数可以具有更长的延迟并且不比原子化。
(1)工作队列有struct workqueue_struct 类型定义在<linux/workqueue.h>:
     使用下面的两个函数之一建立工作队列:
     struct workqueue_struct *create_workqueue(const char *name);//在每个处理器上创建专用线程
     struct workqueue_struct *create_singlethread_workqueue(const char *name);//只在一个处理器上创建专用线程
     在向工作队列提交一个任务时,用下面的宏定义填充一个work_struct结构:
     DECLARE_WORK(name, void (*function) (void *), void *data);//编译时完成
OR
     INIT_WORK(struct work_struct *work, void (*function) (*void), void *data); //运行时构
     PREPARE_WORK(struct work_struct *work, void (*function) (void *), void *data);//造
(2)如果将工作提交到工作队列,则可使用下面的两个函数之一:
     int queue_work(struct workqueue_struct *queue, struct work_struct *work);
     int queue_delayed_work(strcut workqueue_struct *queue, struct work_struct *work, unsigned long delay);
(3)为了确保int cancel_delayed_work(struct workqueue_srtuct *queue )函数返回0之后,工作函数不会系统中任何地方运行,则应该调用下面的函数:
     void flush_workqueue(struct workqueue_struct *queue);
(4)释放相关资源:
     void destroy_workqueue(struct workqueue_struct *queue);
9、共享队列  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LINUX设备驱动第三版_ 前言 第一章 设备驱动程序简介 设备驱动程序的作用 内核功能划分 设备和模块的分类 安全问题 版本编号 许可证条款 加入内核开发社团 本书概要 第二章 构造和运行模块 设置测试系统 Hello World模块 核心模块与应用程序的对比 编译和装载 内核符号表 预备知识 初始化和关闭 模块参数 在用户空间编写驱动程序 快速参考 第三章 字符设备驱动程序 scull的设计 主设备号和次设备号 一些重要的数据结构 字符设备的注册 open和release scull的内存使用 read和write 试试新设备 快速参考 第四章 调试技术 内核中的调试支持 通过打印调试 通过查询调试 通过监视调试 调试系统故障 调试器和相关工具 第五章 并发和竞态 scull的缺陷 并发及其管理 信号量和互斥体 completion 自旋锁 锁陷阱 除了锁之外的办法 快速参考 第六章 高级字符驱动程序操作 ioctl 阻塞型I/O poll和select 异步通知 定位设备 设备文件的访问控制 快速参考 第七章 时间延迟延缓操作 度量时间差 获取当前时间 延迟执行 内核定时器 tasklet 工作队列 快速参考 第八章 分配内存 kmalloc函数的内幕 后备高速缓存 get_free_page和相关函数 vmalloc及其辅助函数 per-CPU变量 获取大的缓冲区 快速参考 第九章 与硬件通信 I/O端口和I/O内存 使用I/O端口 I/O端口示例 使用I/O内存 快速参考 第十章 中断处理 准备并口 安装中断处理例程 实现中断处理例程 顶半部和底半部 中断共享 中断驱动的I/O 快速参考 第十一章 内核的数据类型 使用标准C语言类型 为数据项分配确定的空间大小 接口特定的类型 其他有关移植性的问题 链表 快速参考 第十二章 PCI驱动程序 PCI接口 ISA回顾 PC/104和PC/104+ 其他的PC总线 SBus NuBus 外部总线 快速参考 第十三章 USB驱动程序 USB设备基础 USB和Sysfs USB urb 编写USB驱动程序 不使用urb的USB传输 快速参考 第十四章 Linux设备模型 kobject、kset和子系统 低层sysfs操作 热插拔事件的产生 总线、设备和驱动程序 类 各环节的整合 热插拔 处理固件 快速索引 第十五章 内存映射和DMA Linux的内存管理 mmap设备操作 执行直接I/O访问 直接内存访问 快速参考 第十六章 块设备驱动程序 注册 块设备操作 请求处理 其他一些细节 快速参考 第十七章 网络驱动程序 snull设计 连接到内核 net_device结构细节 打开和关闭 数据包传输 数据包的接收 中断处理例程 不使用接收中断 链路状态的改变 套接字缓冲区 MAC 地址解析 定制 ioctl 命令 统计信息 组播 其他知识点详解 快速参考 第十八章 TTY驱动程序 小型TTY驱动程序 tty_driver函数指针 TTY线路设置 ioctls proc和sysfs对TTY设备的处理 tty_driver结构详解 tty_operations结构详解 tty_struct结构详解 快速参考 参考书目 9112405-1_o.jpg (85.53 KB, 下载次数: 50)
内容简介 《LINUX设备驱动程序(第3版)》已针对Linux内核的2610版本彻底更新过了。内核的这个版本针对常见任务完成了合理化设计及相应的简化,如即插即用、利用sysfs文件系统和用户空间交互,以及标准总线上的多设备管理等等。要阅读并理解本书,您不必首先成为内核黑客;只要您理解C语言并具有Unix系统调用的一些背景知识即可。您将学到如何为字符设备、块设备和网络接口编写驱动程序。为此,《LINUX设备驱动程序(第3版)》提供了完整的示例程序,您不需要特殊的硬件即可编译和运行这些示例程序。《LINUX设备驱动程序(第3版)》还在单独的章节中讲述了PCI、USB和tty(终端)子系统。对期望了解操作系统内部工作原理的读者来讲,《LINUX设备驱动程序(第3版)》也深入阐述了地址空间、异步事件以及I/O等方面的内容。 作者简介 作者:(美)科波特 译者:魏永明 耿岳 钟书毅 Jonahan Corbet早在1981年就开始接触BSD Unix的源代码。那时,科罗拉多大学的一名讲师让他“修正”其中的分页算法。从那时起直到现在。他深入研究了他所遇到的每一个系统,其中包括VAX、Sun、Arden以及x86系统的驱动程序。他在1993年第一次接触Linux系统,从此以后一直从事Linux的开发。Corbet先生是《Linux Weekly News》的创始人和执行主编。他和妻子及两个孩子生活在科罗多州的玻尔得市。 目录 ch00.前言 ch01.第一章 设备驱动程序简介 设备驱动程序的作用 内核功能划分 设备和模块的分类 安全问题 版本编号 许可证条款 加入内核开发社团 本书概要 ch02.第二章 构造和运行模块 设置测试系统 Hello world模块 核心模块与应用程序的对比 编译和装载 内核符号表 预备知识 初始化和关闭 模块参数 在用户空间编写驱动程序 快速参考 ch03.第三章 字符设备驱动程序 scull的设计 主设备号和次设备号 一些重要的数据结构 字符设备的注册 open和release scull的内存使用 read和write 试试新设备 快速参考 ch04.第四章 调试技术 内核中的调试支持 通过打印调试 通过查询调试 通过监视调试 调试系统故障 调试器和相关工具 ch05.第五章 并发和竞态 scull的缺陷 并发及其管理 信号量和互斥体 completiOn 自旋锁 锁陷阱 除了锁之外的办法 快速参考 ch06.第六章 高级字符驱动程序操作 ioctl 阻塞型I/O poll和select 异步通知 定位设备 设备文件的访问控制 快速参考 ch07.第七章 时间延迟延缓操作 度量时间差 获取当前时间 延迟执行 内核定时器 tasklet 工作队列 快速参考 ch08.第八章 分配内存 kmalloc函数的内幕 后备高速缓存 get—free—page和相关函数 vmalloc及其辅助函数 per-CPU变量 获取大的缓冲区 快速参考 ch09... ch10... ... ch18...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值