LDD3 第七章 timer

来源:互联网 发布:windows常用网络命令 编辑:程序博客网 时间:2024/05/21 20:21

下面是从源代码抽离出来的与timer有关的代码。

#include <linux/sched.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/time.h>#include <linux/timer.h>#include <linux/kernel.h>#include <linux/proc_fs.h>#include <linux/types.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <asm/hardirq.h>int delay = HZ; /* the default delay, expressed in jiffies */module_param(delay, int, 0);MODULE_AUTHOR("Alessandro Rubini");MODULE_LICENSE("Dual BSD/GPL");/* * The timer example follows */int tdelay = 10;module_param(tdelay, int, 0);/* This data structure used as "data" for the timer and tasklet functions */struct jit_data {    struct timer_list timer;    struct tasklet_struct tlet;    int hi; /* tasklet or tasklet_hi */    wait_queue_head_t wait;    unsigned long prevjiffies;    unsigned char *buf;    int loops;};#define JIT_ASYNC_LOOPS 5void jit_timer_fn(unsigned long arg){    struct jit_data *data = (struct jit_data *)arg;    unsigned long j = jiffies;    data->buf += sprintf(data->buf, "%9li  %3li     %i    %6i   %i   %s\n",                 j, j - data->prevjiffies, in_interrupt() ? 1 : 0,                 current->pid, smp_processor_id(), current->comm);    if (--data->loops) {        data->timer.expires += tdelay;        data->prevjiffies = j;        add_timer(&data->timer);    } else {        wake_up_interruptible(&data->wait);    }}/* the /proc function: allocate everything to allow concurrency */int jit_timer(char *buf, char **start, off_t offset,          int len, int *eof, void *unused_data){    struct jit_data *data;    char *buf2 = buf;    unsigned long j = jiffies;    data = kmalloc(sizeof(*data), GFP_KERNEL);    if (!data)        return -ENOMEM;    init_timer(&data->timer);    init_waitqueue_head (&data->wait);    /* write the first lines in the buffer */    buf2 += sprintf(buf2, "   time   delta  inirq    pid   cpu command\n");    buf2 += sprintf(buf2, "%9li  %3li     %i    %6i   %i   %s\n",            j, 0L, in_interrupt() ? 1 : 0,            current->pid, smp_processor_id(), current->comm);    /* fill the data for our timer function */    data->prevjiffies = j;    data->buf = buf2;    data->loops = JIT_ASYNC_LOOPS;        /* register the timer */    data->timer.data = (unsigned long)data;    data->timer.function = jit_timer_fn;    data->timer.expires = j + tdelay; /* parameter */    add_timer(&data->timer);    /* wait for the buffer to fill */    wait_event_interruptible(data->wait, !data->loops);    if (signal_pending(current))        return -ERESTARTSYS;    buf2 = data->buf;    kfree(data);    *eof = 1;    return buf2 - buf;}int __init jit_init(void){    create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);  // 创建/proc/jitimer 文件,读取该文件时,jit_timer函数被掉用。    return 0; /* success */}void __exit jit_cleanup(void){    remove_proc_entry("jitimer", NULL);}module_init(jit_init);module_exit(jit_cleanup);

测试:
编译完成放在网络文件系统后插入模块。

读取/proc/jitimer文件

输出为:

 # cat /proc/jitimer    time   delta  inirq    pid   cpu command   -26656    0     0       677   0   cat   -26646   10     1         0   0   swapper   -26636   10     1         0   0   swapper   -26626   10     1         0   0   swapper   -26616   10     1         0   0   swapper   -26606   10     1         0   0   swapper

time是一堆负值???? jiffies不是 unsigned long ,初始值为0吗? --->LDD3 p184

过了一会再次读取time变成正值

# cat /proc/jitimer    time   delta  inirq    pid   cpu command    24538    0     0       672   0   cat    24548   10     1         0   0   swapper    24558   10     1         0   0   swapper    24568   10     1         0   0   swapper    24578   10     1         0   0   swapper    24588   10     1         0   0   swapper

经过查阅,发现jiffies的初始值定义在这里:include/linux/jiffies.h:

/* * Have the 32 bit jiffies value wrap 5 minutes after boot * so jiffies wrap bugs show up earlier. */#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))


说明是有意定义成-300×HZ.

-300 转换成 unsigned long 是很大的一个正数。

long -300 = unsigned long 4294966996

也就是说jiffies会在 300秒后溢出。(300*HZ 表示300秒)

这样做的目的看上面的注释就明白了。

这样做就使得系统在启动后 5 分钟时发生 jiffies 回绕。这么做有利于在早期设备驱动程序因 jiffies 回绕导致的逻辑错误,方便驱动程序的开发。 


参考: http://wenku.baidu.com/view/d7a940f904a1b0717fd5dd49.html