linux驱动设置时间长,linux设备驱动之时间,延迟及延缓操作(实践)

一 jit.函数源码

/*

* 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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/*

* 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; /* the default delay, expressed in jiffies */

module_param(delay, int, 0);

MODULE_AUTHOR("Alessandro Rubini");

MODULE_LICENSE("Dual BSD/GPL");

/* 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();

break;

case JIT_SCHED:

while (time_before(jiffies, j1)) {

schedule();

}

break;

case JIT_QUEUE:

wait_event_interruptible_timeout(wait, 0, delay);

break;

case JIT_SCHEDTO:

set_current_state(TASK_INTERRUPTIBLE);

schedule_timeout (delay);

break;

}

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

len = sprintf(buf, "%9li %9li\n", 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();

do_gettimeofday(&tv1);

tv2 = current_kernel_time();

/* print */

len=0;

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

"%40i.%09i\n",

j1, j2,

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

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

*start = buf;

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 %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;

}

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 %s\n",

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

create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY);

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

二 Makefilewenjian源码

KERNELDIR = /usr/src/linux-headers-2.6.38-8-generic

PWD := $(shell pwd)

obj-m := jit.o

modules:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

三 编译及安装驱动

1  caoyin@caoyin:~/jit$ make

2 root@caoyin:/home/caoyin/jit# insmod ./jit.ko

四 测试例子

a 获取当前时间

root@caoyin:/home/caoyin/jit# head -8 /proc/currentime

b 忙等待

root@caoyin:/home/caoyin/jit# dd bs=20 count=5 < /proc/jitbusy

c 让出处理器

root@caoyin:/home/caoyin/jit# dd bs=20 count=5 < /proc/jitshed

d 超时

root@caoyin:/home/caoyin/jit# dd bs=20 count=5 < /proc/jitqueue

e tasklet的实现

root@caoyin:/home/caoyin/jit# cat /proc/jitasklet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值