LDD3 第七章 timer

下面是从源代码抽离出来的与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 5

void 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

你可能感兴趣的:(LDD3 第七章 timer)