【Linux 驱动】第七章 时间 延迟及延缓操作 (例子详解二)

本文所涉及实验为博文http://blog.csdn.net/tianshuai11/article/details/7465587中示例,请先阅读上述博文,然后消化以下例子

一,模块方法

jiq.c

#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/fs.h>     /* everything... */#include <linux/proc_fs.h>#include <linux/errno.h>  /* error codes */#include <linux/workqueue.h>#include <linux/preempt.h>#include <linux/interrupt.h> /* tasklets *//* * The delay for the delayed workqueue timer file. */static long delay = 1;module_param(delay, long, 0);//传递参数/* * This module is a silly one: it only embeds short code fragments * that show how enqueued tasks `feel' the environment */#define LIMIT(512)/* don't print any more after this size *//* * Print information about the current environment. This is called from * within the task queues. If the limit is reched, awake the reading * process. */static DECLARE_WAIT_QUEUE_HEAD (jiq_wait);static struct work_struct jiq_work;static struct delayed_work jiq_work_delay;/* * Keep track of info we need between task queue runs. */static struct clientdata {int len;char *buf;unsigned long jiffies;unsigned long delay;} jiq_data;#define SCHEDULER_QUEUE ((task_queue *) 1)static void jiq_print_tasklet(unsigned long);static DECLARE_TASKLET(jiq_tasklet, jiq_print_tasklet, (unsigned long)&jiq_data);/* * Do the printing; return non-zero if the task should be rescheduled. */static int jiq_print(void *ptr){struct clientdata *data = ptr;int len = data->len;char *buf = data->buf;unsigned long j = jiffies;if (len > LIMIT) { wake_up_interruptible(&jiq_wait);return 0;}if (len == 0)len = sprintf(buf,"    time  delta preempt   pid cpu command\n");elselen =0;  /* intr_count is only exported since 1.3.5, but 1.99.4 is needed anyways */len += sprintf(buf+len, "%9li  %4li     %3i %5i %3i %s\n",j, j - data->jiffies,preempt_count(), current->pid, smp_processor_id(),current->comm);data->len += len;data->buf += len;data->jiffies = j;return 1;}/* * Call jiq_print from a work queue */static void jiq_print_wq(struct work_struct *ptr)    /* warning: assignment from incompatible pointer type*/{struct clientdata *data = &jiq_data;if (! jiq_print (data))return;if (data->delay)schedule_delayed_work( &jiq_work_delay, data->delay);elseschedule_work(&jiq_work);}static int jiq_read_wq(char *buf, char **start, off_t offset,int len, int *eof, void *data){DEFINE_WAIT(wait);jiq_data.len = 0;                /* nothing printed, yet */jiq_data.buf = buf;              /* print in this place */jiq_data.jiffies = jiffies;      /* initial time */jiq_data.delay = 0;    prepare_to_wait(&jiq_wait, &wait, TASK_INTERRUPTIBLE);schedule_work(&jiq_work);schedule();finish_wait(&jiq_wait, &wait);*eof = 1;return jiq_data.len;}static int jiq_read_wq_delayed(char *buf, char **start, off_t offset,int len, int *eof, void *data){DEFINE_WAIT(wait);jiq_data.len = 0;                /* nothing printed, yet */jiq_data.buf = buf;              /* print in this place */jiq_data.jiffies = jiffies;      /* initial time */jiq_data.delay = delay;    prepare_to_wait(&jiq_wait, &wait, TASK_INTERRUPTIBLE);schedule_delayed_work(&jiq_work_delay, delay);schedule();finish_wait(&jiq_wait, &wait);*eof = 1;return jiq_data.len;}/* * Call jiq_print from a tasklet */static void jiq_print_tasklet(unsigned long ptr){if (jiq_print ((void *) ptr))tasklet_schedule (&jiq_tasklet);}static int jiq_read_tasklet(char *buf, char **start, off_t offset, int len,int *eof, void *data){jiq_data.len = 0;                /* nothing printed, yet */jiq_data.buf = buf;              /* print in this place */jiq_data.jiffies = jiffies;      /* initial time */tasklet_schedule(&jiq_tasklet);interruptible_sleep_on(&jiq_wait);    /* sleep till completion */*eof = 1;return jiq_data.len;}/* * This one, instead, tests out the timers. */static struct timer_list jiq_timer;static void jiq_timedout(unsigned long ptr){jiq_print((void *)ptr);            /* print a line */wake_up_interruptible(&jiq_wait);  /* awake the process */}static int jiq_read_run_timer(char *buf, char **start, off_t offset, int len, int *eof, void *data){jiq_data.len = 0;           /* prepare the argument for jiq_print() */jiq_data.buf = buf;jiq_data.jiffies = jiffies;init_timer(&jiq_timer);              /* init the timer structure */jiq_timer.function = jiq_timedout;jiq_timer.data = (unsigned long)&jiq_data;jiq_timer.expires = jiffies + HZ; /* one second */jiq_print(&jiq_data);   /* print and go to sleep */add_timer(&jiq_timer);interruptible_sleep_on(&jiq_wait);  /* RACE */del_timer_sync(&jiq_timer);  /* in case a signal woke us up */    *eof = 1;return jiq_data.len;}/* * the init/clean material */static int jiq_init(void){/* this line is in jiq_init() */INIT_WORK(&jiq_work, jiq_print_wq);INIT_DELAYED_WORK(&jiq_work_delay, jiq_print_wq);create_proc_read_entry("jiqwq", 0, NULL, jiq_read_wq, NULL);create_proc_read_entry("jiqwqdelay", 0, NULL, jiq_read_wq_delayed, NULL);create_proc_read_entry("jiqtimer", 0, NULL, jiq_read_run_timer, NULL);create_proc_read_entry("jiqtasklet", 0, NULL, jiq_read_tasklet, NULL);return 0; /* succeed */}static void jiq_cleanup(void){remove_proc_entry("jiqwq", NULL);remove_proc_entry("jiqwqdelay", NULL);remove_proc_entry("jiqtimer", NULL);remove_proc_entry("jiqtasklet", NULL);}module_init(jiq_init);module_exit(jiq_cleanup);MODULE_LICENSE("Dual BSD/GPL");

Makefile

KERNELDIR ?= /lib/modules/$(shell uname -r)/build  PWD := $(shell pwd)obj-m := jiq.o modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules modules_install clean

测试:

root@ubuntu:~/桌面/jiq#make

root@ubuntu:~/桌面/jiq# insmod jiq.koroot@ubuntu:~/桌面/jiq# lsmod //查看安装成功

root@ubuntu:~/桌面/jiq# cat /proc/jiqwq time delta preempt pid cpu command 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1 6292513 0 0 235 2 kworker/2:1

root@ubuntu:~/桌面/jiq# cat /proc/jiqwqdelay time delta preempt pid cpu command 6297985 1 0 235 2 kworker/2:1 6297986 1 0 235 2 kworker/2:1 6297987 1 0 235 2 kworker/2:1 6297988 1 0 235 2 kworker/2:1 6297989 1 0 235 2 kworker/2:1 6297990 1 0 235 2 kworker/2:1 6297991 1 0 235 2 kworker/2:1 6297992 1 0 235 2 kworker/2:1 6297993 1 0 235 2 kworker/2:1 6297994 1 0 235 2 kworker/2:1 6297995 1 0 235 2 kworker/2:1

root@ubuntu:~/桌面/jiq# cat /proc/jiqtimer time delta preempt pid cpu command 6304215 0 0 5019 2 cat 6304465 250 256 0 2 kworker/0:1

root@ubuntu:~/桌面/jiq# cat /proc/jiqtasklet time delta preempt pid cpu command 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0 6323656 0 256 3 0 ksoftirqd/0

当你开展的事业从事的行动穷途末路大势已去的时候,

【Linux 驱动】第七章 时间 延迟及延缓操作 (例子详解二)

相关文章:

你感兴趣的文章:

标签云: