Chinaunix首页 | 论坛 | 博客
  • 博客访问: 439102
  • 博文数量: 71
  • 博客积分: 26
  • 博客等级: 民兵
  • 技术积分: 1246
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-23 14:46
个人简介

linux --- 一切皆文件

文章分类

全部博文(71)

文章存档

2021年(1)

2019年(2)

2018年(4)

2017年(7)

2016年(11)

2015年(1)

2014年(2)

2013年(33)

2012年(10)

分类: LINUX

2013-10-12 22:00:08

内核时间:
1: tick:
1 tick = 1/HZ秒
HZ是在make menuconfig里配置的,.config中的CONFIG_HZ,
6410设置的是200,其他取值一般为:100,200,250,300,1000,范围是100-1000
2: 相对时间jiffies
jiffies记录着从开机到当前所经过的tick时间,在硬件定时器中断处理函数中对jiffies进行++
jiffies是 unsigned long 类型的,
所以当HZ  = 1000的时候,49.7天的时候就会发生溢出,为了解决这个问题,可以使用jiffies64
u64 j64;
j64 = get_jiffies_64();
jiffes开机的时候等于-300 * HZ就相当于开机五分钟要进位一次,之后就是49.7天进位一次
内核中很多延迟和定时都是用jiffies进行判定


3: 绝对时间,从1970年1月1日0时0分0秒开始到现在的时间。
可以存放绝对时间的值 中的timeval和timespec。
#include
struct timeval val; 最小单位微妙
struct timespec val; 最小单位纳秒
do_gettimeofday(&val); printf("s = %ld us = %ld \n",val.tv_sec,val.tv_usec);
getnstimeofday(&val); printf("s = %ld, ns = %ld \n",val.tv_sec,val.tv_nsec);


4: 延迟
延迟:迫不得已的,为了等待某件事情完成或者某个条件满足而产生了延迟。
定时:启动定时器,内核在将来的某个特定的时间启动定时器完成特定的功能。


当写某些硬件设备的时候可能需要等待足够的时间让硬件操作,所以可以延迟,延迟方法有一下两种:
1: 短时间的延迟,基于忙循环
#include
ndelay(10); //延迟10ns
udelay(20); //延迟20us
mdelay(30); //延迟30ms


2: 长时间的延迟,基于睡眠的以tick为单位进行睡眠:
这样的任务就会从运行队列转移到休眠队列,等到时间到了,系统自动把这个任务从睡眠队列加入到运行队列等待调度。
struct task {
    int status; --- |TASK_RUNNING
}                     |TASK_INTERRUPT //睡眠的时候能够接受信号
                        |TASK_UNINTERRUPT //睡眠的时候不能接受到信号
                        //内核是有运行态睡眠态,没有就绪态,如果状态是TASK_INTERRUPT/TASK_UNINTERRUPT这两个状态,则将任务移动到睡眠队列
                        |__TASK_STOP
                        |__TASK_THREAD
                        |EXIT_ZOMBIE
                        |EXIT_DEAD
                        |TASK_DEAD
                ****中断打断的是正在运行的进程,就是从内核态想用户态的过程中检测信号,并且执行信号的处理函数。


实现如下:
set_current_state(TASK_INTERRUPT/TASK_UNINTERRUPT);
schedule_timeout(3 * HZ); //以tick为单位,1S有HZ个tick,3 *HZ则说明休眠三秒

3:基于等待队列的的延迟
每个等待的条件都要有一个等待队列
每个队列有一个等待队列头(wait_queue_head_t)
等待队列定义在


wait_queue_head_t mywait; //申明初始化等待队列


init_waitqueue_head(&mywait); //初始化等待队列


//当需要等待某个条件满足的时就调用wait_event_interruptible(),第一个参数是等待队列的头,第二个参数是唤醒是检查的条件等价如下:
//while(!dev-wp!=dev->buf_size){
// 进行休眠
//}检测代码wait_event已经时间了
在APUE中,使用条件互斥的时候在唤醒后也要查是否条件真的满足
wait_event_interruptible(mywait, dev-wp!=dev->buf_size);  //wait_event(mywait, dev->wp!=dev->buf_size);

//如果条件满足,则会唤醒对应队列上的所有任务去检查,如果抢到则运行,没有则继续睡眠
wake_up_interruptible(&mywait); //wake_up(&mywait);


5:定时
1:启动定时器的人和执行定时器任务的人不一样
一般定时器的设定或者启动者一般是进程或者中断,而执行者一般是内核的硬件定时器处理函数


2:定时器是未来的一段时间运行的


3:定时器函数只执行一次,如果要多次执行,则要在定时器函数中再次启动定时器


4:定时器函数在中断上下文中运行,所以不能有休眠


定时器的核心结构体定义在

#include
struct timer_list mytimer; 申明定时器


setup_timer(&mytimer, my_timer_func, data); 设置定时器处理函数,data是传给定时处理函数的参数,一般为私有结构体


mod_timer(&mytimer, jiffies+100); 设置将来的时间,并且启动定时器
//add_timer() 将定时器重新加入到队列中


del_timer(&mytimer); 删除定时器



*********使用cpu_idel()函数会是CPU进入空闲状态,低电模式。ARM的CPU,当调用这个函数的时候回去设置CP15协处理器
阅读(5423) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~