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

来源:互联网 发布:美工培训视频基础知识 编辑:程序博客网 时间:2024/05/22 17:11

本文所涉及实验为博文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.ko
root@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







原创粉丝点击