这里跟我们经常用到就是jiffies,时钟节拍。
jiffies是记录着从电脑开机到现在总共的时钟中断次数。在linux内核中jiffies取决于系统的频率,单位是Hz,这里不得不说一下频率的单位,1MHz=1000,000Hz(6个零),1KHz=1000Hz(3个零)频率是周期的倒数,一般是一秒钟中断产生的次数,所以,假如我们需要知道系统的精确的时间单位时,需要换算了,假如我们系统的频率是200Mhz,那么一次中断的间隔是1秒/200,000,000Hz=0.000 000 005秒看一下上面我们的时间单位,对照一下小数点后面是9个零,所以理论上我们系统的精确度是5纳秒。LINUX系统时钟频率是一个常数HZ来决定的,通常HZ=100,那么他的精度度就是10ms(毫秒)。也就是说每10ms一次中断。所以一般来说Linux的精确度是10毫秒。
在Linux 2.6 中,系统时钟每 1 毫秒中断一次(时钟频率,用 HZ 宏表示,定义为 1000,即每秒中断1000 次,2.4中定义为 100,很多应用程序也仍然沿用 100 的时钟频率),这个时间单位称为一个jiffie
![](https://img-blog.csdn.net/20170929091941583?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWl9IVUFMSU4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
内核定时器
1.涉及函数
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
setup_timer(timer, fn, data)
add_timer(&buttons_timer);
mod_timer(&buttons_timer, jiffies+HZ/100);
del_timer(&timer);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
2.demo
工作队列通过定时器超时函数自动调度工作
#include linux/init.h>
#include linux/module.h>
#include linux/moduleparam.h>
#include linux/time.h>
#include linux/timer.h>
#include linux/workqueue.h>
#include asm/atomic.h>
MODULE_AUTHOR("lcw");
MODULE_LICENSE("GPL");
struct timer_data {
struct timer_list timer;
struct workqueue_struct *work_queue;
unsigned long prev_jiffies;
unsigned int loops;
};
static struct timer_list timer1;
static struct timer_list timer2;
static void do_work(void *);
static DECLARE_WORK(test_work, do_work, NULL);
static DECLARE_WORK(test_work1, do_work, NULL);
static struct workqueue_struct *test_workqueue;
atomic_t wq_run_times;
unsigned int failed_cnt = 0;
void test_timer_fn1(unsigned long arg)
{
struct timer_data *data = (struct timer_data *)arg;
mod_timer(&timer1, jiffies+HZ/100);
if (queue_work(test_workqueue, &test_work)== 0) {
printk("Timer (0) add work queue failed\n");
(*(&failed_cnt))++;
}
data->loops++;
printk("timer-0 loops: %u\n", data->loops);
}
void test_timer_fn2(unsigned long arg)
{
struct timer_data *data = (struct timer_data *)arg;
mod_timer(&timer2, jiffies+HZ/100);
if (queue_work(test_workqueue, &test_work1)== 0) {
printk("Timer (1) add work queue failed\n");
(*(&failed_cnt))++;
}
data->loops++;
printk("timer-1 loops: %u\n", data->loops);
}
void do_work(void*arg)
{
atomic_inc(&wq_run_times);
printk("====work queue run times: %u====\n", atomic_read(&wq_run_times));
printk("====failed count: %u====\n",*(&failed_cnt));
}
int wq_init(void)
{
atomic_set(&wq_run_times, 0);
test_workqueue = create_singlethread_workqueue("test-wq");
init_timer(&timer1);
timer1.function= test_timer_fn1;
add_timer(&timer1);
init_timer(&timer2);
timer2.function= test_timer_fn1;
add_timer(&timer2);
mod_timer(&timer1, jiffies+HZ/100);
mod_timer(&timer2, jiffies+HZ/100);
return 0;
}
void wq_exit(void)
{
del_timer(&test_data.timer);
del_timer(&test_data1.timer);
destroy_workqueue(test_workqueue);
printk("wq exit success\n");
}
module_init(wq_init);
module_exit(wq_exit)