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

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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值