Chinaunix首页 | 论坛 | 博客
  • 博客访问: 369439
  • 博文数量: 146
  • 博客积分: 2990
  • 博客等级: 少校
  • 技术积分: 1399
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-09 22:09
文章分类

全部博文(146)

文章存档

2011年(1)

2010年(2)

2009年(143)

我的朋友

分类: LINUX

2009-03-10 11:05:36

在linux中,时钟中断由系统定时器一周期性的间隔产生,这个间隔有内核根据Hz的值决定,Hz是一个与体系结构有关的常数,定义在或者该文件包含的某个子平台的相关文件中,对真实的硬件,已发布的linux内核源代码为大多数的平台定义的默认Hz值为50~120,对软件方针的Hz为24.多数平台每秒有100或1000次的时钟中断,常见的x86PC平台上,默认为1000,作为一般的规则,即使知道对应平台的Hz值,也不应该在编程时倚赖Hz的值.

1:在linux内核中每当时钟发声中断时,内核内部计数器的值就会自动加一,这个值在系统引导时被初始化为0,因此,他的值就是子上次操作系统引导以来的时钟滴答数,这个值为jiffies为unsigned long的变量,该变量为valititle,这样可以避免编译器对该变量的语句优化,包含在文件中.

2:延迟执行,优势驱动程序要延迟比较长的时间,即长于一个时钟滴答.要实现这个类刑的延迟有好多方法,一种就事忙延迟,利用while循环例如:
while(time_before(jiffies,j1))
{
cpu_relax();
}
在这里time_before()函数会比较两个jiffies值,其中,如果jiffies在j1之前,就返回true,所以这个简单的循环可以实现延迟,但是有一个很重要的缺点就是,如果在进入循环之前禁止了中断,也就是说时钟滴答不会更新,那么这个循环就永远不会退出.

3:利用超时:类似与windows中的waitforsignalobject一样.在linux中以规定的时间等待某个事件.常见的函数为wait_event_timeout(wait_queue_head_t q,condition,long time_out)和wait_event_interruptible_timeout(wait_queue_head_t q,condition,long timeout);
在这里timeout的数值为要等待的jiffies值,不是绝对的时间值.
实现的方法如下
wait_queue_head_t wait;
init_waitqueue_head(&wait);
wait_event_interruptiable_timeout(wait,0,delay);

4:短延迟.当设备驱动程序要处理营建的延迟时,折中延迟通常最多涉及到几个毫秒,在折中状态下,倚赖于时钟滴答数显然不是正确的方法.在内核中提供了如下几个方便的函数void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);void mdelay(unsigned long msecs);分别为延迟纳秒,微秒和毫秒.

5:内核定时器,如果我们要在将来的某个时间点调度执行某个动作,同事在该时间点到达之前不会堵塞当前的进程,则应该使用内核定时器.内核定时器可以用来在未来的某个特定的时间点执行某个函数,从而完成许多事物;例如如果硬件无法产生中断,则用内核定时器周期性的轮巡设备.
与内核定时器相关的API有add_timer和del_timer,在文件中有个
struct timer_list
{
unsigned long expires;与jiffies的值
void (*function)(unsigned long);到达时间值后回调的函数
unsigned long data;传递给在回调函数的值
}

例如:
unsigned long j = jiffies;
data->prevjiffies=j;
data->buf=buf2;
data->loops=JIT_ASYNC_LOOPS;

data->timer.data = (unsigned long)data;
data->timer.function = jit_time_fun;
data->timer.expires = j + delay;
add_timer(&data->timer);
wait_event_interruptible(data->wait,!data->loops);


void jit_time_fun(unsigned long arg)
{
struct jit_data * data = (struct jit_data*)arg;
unsigned long j = jiffies;
if(--data->loops)
{
data->timer.expires += tdelay;
data->prevjiffies = j;
add_timer(&data->times);
}
else
{
wake_up_interruptible(&data->wait);
}
}

6:tasklet

与内核定时器相比,tasklet和内核定时器很相似,唯一的区别是我们不能要求tasklet在某个给定的时间执行,tasklet典型的应用是在中断服务函数中,硬件中断时要求尽可能快的管理硬件中断,而大部分的数据管理可以安全的延迟到厚漆执行.
阅读(409) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~