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

原创 2012年03月21日 17:23:17

一 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 <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/param.h>
#include <linux/wait.h>
#include <linux/jiffies.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; /* 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



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

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

度量时间差 时钟中断由系统定时硬件以周期性的间隔产生,这个间隔由内核根据 HZ 值来设定,HZ 是个体系依赖的值,在 中定义或该文档包含的某个子平台相关文档中。作为通用的规则,即便假如知道 ...

Linux设备驱动程序第三版学习(10)- 时间、延迟及延缓操作

接下来学习第七章:时间、延迟及延缓操作。本章主要学习了内核代码如何对时间问题进行处理。 关于Linux时钟处理机制的详细内容,参考本博客转载的“Linux 时钟处理机制”一文【赵 健博 (zhao...

Linux设备驱动程序第三版学习(10)- 时间、延迟及延缓操作

接下来学习第七章:时间、延迟及延缓操作。本章主要学习了内核代码如何对时间问题进行处理。 关于Linux时钟处理机制的详细内容,参考本博客转载的“Linux 时钟处理机制”一文【赵 健博 (zhaoji...

【原创】《Linux设备驱动程序》学习之循序渐进 --- 时间、延迟及延缓操作

【原创】《Linux设备驱动程序》学习之循序渐进 --- 时间、延迟及延缓操作 第七章

linux设备驱动归纳总结(七):1.时间管理与内核延时

linux设备驱动归纳总结(七):1.时间管理与内核延时 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...

Linux 字符设备驱动开发--内存读写操作

学习Linux的累计时间已经有两年多了,工作关系,学习的过程总是断断续续的,现在整理一下,下面要分享的是一个简单的linux驱动程序,没有什么实际的用处,像hello wold!程序一样,我们简单体会...

linux设备驱动归纳总结(五):2.操作硬件——IO内存

转自:http://blog.chinaunix.net/uid-25014876-id-80627.html linux设备驱动归纳总结(五):2.操作硬件——IO内存 xxxxxxxxxx...

3、Linux设备驱动---轮询操作poll()函数

1.轮询的概念和作用    使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可对设备进行无阻塞的访问。select()和poll()系统调用最终会引发设备驱动中的p...

Linux 设备驱动 ====> 并发控制 --- 原子操作

原子操作 原子的操作指的就是在执行过程中不会被别的代码所中断的操作。 在Linux中原子操作的方法有很多,有整型原子和位原子,他们在任何情况下操作都是原子的,这些原子操作的实现都是依赖CPU来实现...

Linux简单设备驱动(1):使用IO内存操作GPIO--LED

Linux简单设备驱动(1):使用IO内存操作GPIO–LED前言本人是从ARM7和cortex-Mx系列单片机,向linux转型的初学者。本文主要是总结怎么通过操作芯片的GPIO外设寄存器完成LED...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)