您的位置:首页 > 运维架构 > Linux

Linux设备驱动程序学习(10)-时间、延迟及延缓操作(Jit.c)

2014-04-03 15:15 501 查看
以下代碼基本演示了Linux设备驱动程序学习(10)-时间、延迟及延缓操作的所有知識

点击(此处)折叠或打开

/*

* jit.c -- the
just-in-time module

*

* Copyright (C) 2001,2003
Alessandro Rubini and Jonathan Corbet

* Copyright (C) 2001,2003
O'Reilly & Associates

*

* The source code in this file can be freely used, adapted,

* and redistributed in source or binary form, so
long as an

* acknowledgment appears in derived source files. The citation

* should list that the code comes from the book "Linux Device

* Drivers" by Alessandro Rubini and Jonathan Corbet, published

* by O'Reilly & Associates. No
warranty is attached;

* we cannot take responsibility for errors or fitness for use.

*

* $Id: jit.c,v
1.16 2004/09/26 07:02:43
gregkh Exp $

*/

//#include <linux/config.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 <linux/sched.h>

#include <asm/hardirq.h>

/*

* This module is a silly one: it only embeds short code fragments

* that show how time delays can be handled in the kernel.

*/

int delay = HZ; /* s3c24x0
HZ= 200*/

module_param(delay, int, 0);

/* use these as data pointers, to implement
four files in one function */

enum jit_files {

JIT_BUSY,

JIT_SCHED,

JIT_QUEUE,

JIT_SCHEDTO

};

/*

* This function prints one line of data, after sleeping one second.

* It can sleep in different ways, according to the
data pointer

*/

int jit_fn(char *buf, char **start, off_t
offset,

int len, int *eof, void *data)

{

unsigned long j0, j1; /* jiffies */

wait_queue_head_t wait;

init_waitqueue_head (&wait);

j0 = jiffies;

j1 = j0 + delay;

switch((long)data) {

case JIT_BUSY:

while (time_before(jiffies, j1))

cpu_relax();

printk("cpu_relax()n");

break;

case JIT_SCHED:

while (time_before(jiffies, j1)) {

schedule();

printk("schedule()n");

}

break;

case JIT_QUEUE:

wait_event_interruptible_timeout(wait, 0, delay);

printk("one wait event for %d s",delay);

break;

case JIT_SCHEDTO:

set_current_state(TASK_INTERRUPTIBLE);

schedule_timeout (delay);

printk("two wait event for %d s",delay);

break;

}

j1 = jiffies; /* actual
value after we delayed */

len = sprintf(buf, "%9li
%9lin", j0, j1);

*start = buf;

return len;

}

/*

* This file, on the other hand, returns
the current time forever

*/

int jit_currentime(char *buf, char **start, off_t
offset,

int len, int *eof, void *data)

{

struct timeval tv1;

struct timespec tv2;

unsigned long j1;

u64 j2;

/* get them four */

j1 = jiffies;

j2 = get_jiffies_64();

//use two method to get the time

do_gettimeofday(&tv1);

tv2 = current_kernel_time();

/* print */

len=0;

printk("the length is : %dn",len);

len += sprintf(buf,"0x%08lx
0x%016Lx %10i.%06in"

"%40i.%09in",

j1, j2,

(int) tv1.tv_sec, (int) tv1.tv_usec,

(int) tv2.tv_sec, (int) tv2.tv_nsec);

//here you can choose to show the message till you don't
want (know the use of start)

*start = buf; /*if you
want currentime to output only onec ,disable this

return len;

}

/*

* 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 %sn",

j, j - data->prevjiffies, in_interrupt() ? 1 : 0,

current->pid, smp_processor_id(), current->comm);

if (--data->loops)

{

data->prevjiffies = j;

mod_timer(&data->timer, data->timer.expires+tdelay);

}

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 commandn");

buf2 += sprintf(buf2, "%9li
%3li %i %6i %i %sn",

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;

//del_timer(&data->timer);

kfree(data);

*eof = 1;

return buf2 - buf;

}

void jit_tasklet_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 %sn",

j, j - data->prevjiffies, in_interrupt() ? 1 : 0,

current->pid, smp_processor_id(), current->comm);

if (--data->loops) {

data->prevjiffies = j;

if (data->hi)

tasklet_hi_schedule(&data->tlet);

else

tasklet_schedule(&data->tlet);

}

else

{

wake_up_interruptible(&data->wait);

}

}

/* the /proc function: allocate
everything to allow concurrency */

int jit_tasklet(char *buf, char **start, off_t
offset,

int len, int *eof, void *arg)

{

struct jit_data *data;

char *buf2 = buf;

unsigned long j = jiffies;

long hi = (long)arg;

data = kmalloc(sizeof(*data), GFP_KERNEL);

if (!data)

return -ENOMEM;

init_waitqueue_head (&data->wait);

/* write the first lines in the buffer */

buf2 += sprintf(buf2, "
time delta inirq pid cpu commandn");

buf2 += sprintf(buf2, "%9li
%3li %i %6i %i %sn",

j, 0L, in_interrupt() ? 1 : 0,

current->pid, smp_processor_id(), current->comm);

/* fill the data for our tasklet function */

data->prevjiffies = j;

data->buf = buf2;

data->loops = JIT_ASYNC_LOOPS;

/* register the tasklet */

tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned
long)data);

data->hi = hi;

if (hi)

tasklet_hi_schedule(&data->tlet);

else

tasklet_schedule(&data->tlet);

/* 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("currentime", 0, NULL, jit_currentime, NULL);

//the method to use tranamit a data

create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY/*pay
more attention here*/);

create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);

create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);

create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);

create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);

create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);

create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);

return 0; /* success */

}

void __exit jit_cleanup(void)

{

remove_proc_entry("currentime", NULL);

remove_proc_entry("jitbusy", NULL);

remove_proc_entry("jitsched", NULL);

remove_proc_entry("jitqueue", NULL);

remove_proc_entry("jitschedto", NULL);

remove_proc_entry("jitimer", NULL);

remove_proc_entry("jitasklet", NULL);

remove_proc_entry("jitasklethi", NULL);

}

module_init(jit_init);

module_exit(jit_cleanup);

MODULE_AUTHOR("Alessandro Rubini ( modified by tekkaman )");

MODULE_LICENSE("Dual BSD/GPL");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: