2.6.36 Workqueue API usage

在新版的linux中,workqueue的api做了一定的修改。

下面是个简单的例子,是基于ldd3的 jiq.c代码。

 

其中网上另一个人给的一个用法是,将jiq_print_wq的输入参数作为一个全局的变量,而不是通过container_of来算出来的。

我觉得这样写代码比较清楚点。

 

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

MODULE_LICENSE("Dual BSD/GPL");

/*
 * 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    (PAGE_SIZE-128)    /* don't print any more after this size */
#define LIMIT    (PAGE_SIZE-3072)    /* 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);

/*
 * Keep track of info we need between task queue runs.
 */
static struct clientdata {
//static struct work_struct jiq_work;
    struct delayed_work  jiq_work;
    int len;
    char *buf;
    unsigned long jiffies;
    long delay;
} jiq_data;

#define SCHEDULER_QUEUE ((task_queue *) 1)

/*
 * 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");
    else
        len =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 *work)
{
//    struct clientdata *data = (struct clientdata *) ptr;
    struct clientdata *data = container_of(work, struct clientdata, jiq_work.work) ;
   
    if (! jiq_print (data))
        return;
   
    if (data->delay)
        schedule_delayed_work(&data->jiq_work, data->delay);
    else
        schedule_work(&data->jiq_work.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_data.jiq_work.work);
    schedule();
    finish_wait(&jiq_wait, &wait);

    *eof = 1;
    return jiq_data.len;
}

/*
 * the init/clean material
 */

static int workqueue_init(void)
{

    /* this line is in jiq_init() */
    INIT_DELAYED_WORK(&jiq_data.jiq_work, jiq_print_wq );

    create_proc_read_entry("workqueue", 0, NULL, jiq_read_wq, NULL);

    return 0; /* succeed */
}

static void workqueue_cleanup(void)
{
    remove_proc_entry("workqueue", NULL);
}


module_init(workqueue_init);
module_exit(workqueue_cleanup);

你可能感兴趣的:(2.6.36 Workqueue API usage)