设备驱动常常需要延后一段时间来执行一个特定片段的代码,常常允许硬件完成某个任务。
2、时间管理
#include<linux/param.h>
HZ
HZ符号指定了每秒产生的时钟嘀哒的数目.
#include<linux/jiffies.h>
volatileunsignedlongjiffies;
u64jiffies_64;
jiffies_64变量每个时钟嘀哒时被递增;因此,它是每秒递增HZ次.内核代码几乎常常引用
jiffies,它在64-位平台和jiffies_64相同并且在32-位平台是它低有效的一半.
inttime_after(unsignedlonga,unsignedlongb);
inttime_before(unsignedlonga,unsignedlongb);
inttime_after_eq(unsignedlonga,unsignedlongb);
inttime_before_eq(unsignedlonga,unsignedlongb);
这些布尔表达式以一种安全的方式比较jiffies,没有万一计数器溢出的问题和不需要存取
jiffies_64.
u64get_jiffies_64(void);
获取jiffies_64而没有竞争条件.
#include<linux/time.h>
unsignedlongtimespec_to_jiffies(structtimespec*value);
voidjiffies_to_timespec(unsignedlongjiffies,structtimespec*value);
unsignedlongtimeval_to_jiffies(structtimeval*value);
voidjiffies_to_timeval(unsignedlongjiffies,structtimeval*value);
在jiffies和其他表示之间转换时间表示.
#include<asm/msr.h>
rdtsc(low32,high32);
rdtscl(low32);
rdtscll(var32);
x86-特定的宏定义来读取时戳计数器.它们作为2半32-位来读取,只读低一半,或者全部读
到一个longlong变量.
#include<linux/timex.h>
cycles_tget_cycles(void);
以平台独立的方式返回时戳计数器.如果CPU没提供时戳特性,返回0.
#include<linux/time.h>
unsignedlongmktime(year,mon,day,h,m,s);
返回自Epoch以来的秒数,基于6个unsignedint参数.
voiddo_gettimeofday(structtimeval*tv);
返回当前时间,作为自Epoch以来的秒数和微秒数,用硬件能提供的最好的精度.在大部分的
平台这个解决方法是一个微秒或者更好,尽管一些平台只提供jiffies精度.
structtimespeccurrent_kernel_time(void);
返回当前时间,以一个jiffy的精度.
3、延迟
#include<linux/wait.h>
longwait_event_interruptible_timeout(wait_queue_head_t*q,condition,signedlongtimeout);
使当前进程在等待队列进入睡眠,安装一个以jiffies表达的超时值.使用schedule_timeout(下
面)给不可中断睡眠.
#include<linux/sched.h>
signedlongschedule_timeout(signedlongtimeout);
调用调度器,在确保当前进程在超时到的时候被唤醒后.调用者首先必须调用set_curret_state
来使自己进入一个可中断的或者不可中断的睡眠状态.
#include<linux/delay.h>
voidndelay(unsignedlongnsecs);
voidudelay(unsignedlongusecs);
voidmdelay(unsignedlongmsecs);
引入一个整数纳秒,微秒和毫秒的延迟.获得的延迟至少是请求的值,但是可能更多.每个函
数的参数必须不超过一个平台特定的限制(常常是几千).
voidmsleep(unsignedintmillisecs);
unsignedlongmsleep_interruptible(unsignedintmillisecs);
voidssleep(unsignedintseconds);
使进程进入睡眠给定的毫秒数(或者秒,如果使ssleep).
4、内核定时器
#include<asm/hardirq.h>
intin_interrupt(void);
intin_atomic(void);
返回一个布尔值告知是否调用代码在中断上下文或者原子上下文执行.中断上下文是在一
个进程上下文之外,或者在硬件或者软件中断处理中.原子上下文是当你不能调度一个中断
上下文或者一个持有一个自旋锁的进程的上下文.
#include<linux/timer.h>
voidinit_timer(structtimer_list*timer);
structtimer_listTIMER_INITIALIZER(_function,_expires,_data);
这个函数和静态的定时器结构的声明是初始化一个timer_list数据结构的2个方法.
voidadd_timer(structtimer_list*timer);
注册定时器结构来在当前CPU上运行.
intmod_timer(structtimer_list*timer,unsignedlongexpires);
改变一个已经被调度的定时器结构的超时时间.它也能作为一个add_timer的替代.
inttimer_pending(structtimer_list*timer);
宏定义,返回一个布尔值说明是否这个定时器结构已经被注册运行.
voiddel_timer(structtimer_list*timer);
voiddel_timer_sync(structtimer_list*timer);
从激活的定时器链表中去除一个定时器.后者保证这定时器当前没有在另一个CPU上运行.
5、Tacklets机制
#include<linux/interrupt.h>
DECLARE_TASKLET(name,func,data);
DECLARE_TASKLET_DISABLED(name,func,data);
voidtasklet_init(structtasklet_struct*t,void(*func)(unsignedlong),unsignedlongdata);
前2个宏定义声明一个tasklet结构,而tasklet_init函数初始化一个已经通过分配或其他方式
获得的tasklet结构.第2个DECLARE宏标识这个tasklet为禁止的.
voidtasklet_disable(structtasklet_struct*t);
voidtasklet_disable_nosync(structtasklet_struct*t);
voidtasklet_enable(structtasklet_struct*t);
禁止和使能一个tasklet.每个禁止必须配对一个使能(你可以禁止这个tasklet即便它已经被
禁止).函数tasklet_disable等待tasklet终止如果它在另一个CPU上运行.这个非同步版本不
采用这个额外的步骤.
voidtasklet_schedule(structtasklet_struct*t);
voidtasklet_hi_schedule(structtasklet_struct*t);
调度一个tasklet运行,或者作为一个"正常"tasklet或者一个高优先级的.当软中断被执行,高
优先级tasklets被首先处理,而正常tasklet最后执行.
voidtasklet_kill(structtasklet_struct*t);
从激活的链表中去掉tasklet,如果它被调度执行.如同tasklet_disable,这个函数可能在SMP系
统中阻塞等待tasklet终止,如果它当前在另一个CPU上运行.
6、工作队列
#include<linux/workqueue.h>
structworkqueue_struct;
structwork_struct;
这些结构分别表示一个工作队列和一个工作入口.
structworkqueue_struct*create_workqueue(constchar*name);
structworkqueue_struct*create_singlethread_workqueue(constchar*name);
voiddestroy_workqueue(structworkqueue_struct*queue);
创建和销毁工作队列的函数.一个对create_workqueue的调用创建一个有一个工作者线程在
系统中每个处理器上的队列;相反,create_singlethread_workqueue创建一个有一个单个工作
者进程的工作队列.
DECLARE_WORK(name,void(*function)(void*),void*data);
INIT_WORK(structwork_struct*work,void(*function)(void*),void*data);
PREPARE_WORK(structwork_struct*work,void(*function)(void*),void*data);
声明和初始化工作队列入口的宏.
intqueue_work(structworkqueue_struct*queue,structwork_struct*work);
intqueue_delayed_work(structworkqueue_struct*queue,structwork_struct*work,unsignedlongdelay);
从一个工作队列对工作进行排队执行的函数.
intcancel_delayed_work(structwork_struct*work);
voidflush_workqueue(structworkqueue_struct*queue);
使用cancel_delayed_work来从一个工作队列中去除入口;flush_workqueue确保没有工作队列入口在系统中任何地方运行.
intschedule_work(structwork_struct*work);
intschedule_delayed_work(structwork_struct*work,unsignedlongdelay);
voidflush_scheduled_work(void);
使用共享队列的函数.
相关推荐
LDD3学习笔记设备模型之底层实现(kobject,kset)[汇编].pdf
ldd code ldd3驱动源代码 ldd code ldd3驱动源代码
ldd3中文版、chmldd3中文版chm
本资源为ldd3详解,该书中详细介绍了ldd3的使用以及各种驱动的设置
LDD-LinuxDeviceDrivers#1书籍-一些书中的原始码和范例目录书籍#2 study--本人的linux学习以及驱动代码目录书籍学习Linux内核的设计与实现,包括文档和示例代码,文档与同步更新自己实现的一些linux内核的驱动代码...
LDD3配套源码,配合我的百度云分享的虚拟机可以直接编译运行(虚拟机另行在我上传的资源里下载,相关可以参考我的LDD3系列博客)
ldd3 中文
LDD2+LDD3 linux设备驱动
Linux 设备驱动 Edition 3 - LDD3中文版,学习linux必备之书,pdf格式
ldd3-examples-3.x, 在 linux 3.x 之后,端口LDD3源代码示例 ldd3-examples-3.xlinux 3 。x 之后LDD3源代码示例的端口背景LDD3是Linux设备驱动程序,第三版。 这是一本关于如何编写linux设备驱动程序的。 你可以从 ...
经典 LDD3,linux驱动开发 linux驱动开发
由于对Linux设备驱动程序设计的需求,所以前段时间在网上下载了LDD3的HTML格式文档,在看的时候感觉不太好看,同时为了打印方便,把它转化为PDF格式,所以在此与大家一起分享。 由于本资料不是本人自创,也是来自于...
这是ldd3的英文原版书以及相应例程的源码,希望对正在学习linux驱动的朋友们有所帮助
LDD3是linux驱动开发的基础入门级图书,适合刚接触linux驱动的新手学习。
LDD6410 S3C6410开发板原理图
主要是对LDD3中的实例进行测试,修改,调试。
linux LDD 3 LINUX设备驱动程序源码。。
linux device driver\ldd3英文版附源码.rar
ldd3 example ldd3 example