linux内核学习——工作队列

由于CPU要处理中断,而且中断都要求尽快执行结束,所以对于大量的程序处理都会放到下半部去执行。常用的下半部有:软中断、任务队列、工作队列等。

其中工作队列是一个比较好用,也比较常用的方法。


工作队列使用时我觉得一般会有以下几部分来共同使用。

struct workqueue_struct my_wq;    //工作队列,用于通知工作者工作
struct work_struct my_work;       //工作者,用于处理具体的工作任务
struct list_head my_list;         //任务链表,用于存放工作任务
spinlock_t my_spin_lock;          //自旋锁,用于线程间同步

如下是一个例子(未编译,可能会有瑕疵):

my_workqueue.c

#include "my_workqueue.h"
#include "public.h"

struct workqueue_struct *my_wq;    //工作队列,用于通知工作者工作
struct work_struct my_work;       //工作者,用于处理具体的工作任务
struct list_head my_work_list;    //任务链表,用于存放工作任务
spinlock_t my_spin_lock;          //自旋锁,用于线程间同步

//定义任务结构体
typedef struct req
{
    struct list_head list;
    char * data;
}req_t;

void init(void)
{
    my_wq = create_singlethread_workqueue("my_workqueue");
    if (NULL == my_wq)
    {
        DBG_PRINT("Failed to alloc memory");
        return ;
    }
    
    INIT_WORK(&my_work, handle_work);
    spin_lock_init(my_spin_lock);
}

void exit(void)
{
    flush_workqueue(my_wq);
    destroy_workqueue(my_wq);
}

void proc_req(req_t * req)
{
    DBG_PRINT("I am req %s", req->data);
    //这里需要释放内存,防止内存泄露
    my_free(req);
    
    return ;
}

void handle_work(struct work_struct *work)
{
    unsigned long flags = 0;
    req_t *req = NULL;
    
    (void)work; //消除编译告警
    
    spin_lock_irqsave(my_spin_lock, flags);
    while (trur)
    {
        list_remove_head(my_work_list, req, req_t, list);
        if (NULL == req)
        {
            spin_unlock_irqrestore(my_spin_lock, flags);
            return ;
        }
        
        proc_req(req);
    }
    
    return ;
}

void create_work(void)
{
    req_t *req = NULL;
    char data[] = "hello"; 
    
    req = malloc(sizeof(req_t));
    if (NULL == req)
    {
        DBG_PRINT("Failed to alloc memory");
        return ;
    }
    
    req.data = my_alloc(sizeof(data));
    memset(req.data, 0, sizeof(data));    //正常使用的话数据应该是从外部传进来的。这里只是模拟
    memcpy(req.data, data, sizeof(data));
    
    spin_lock_irqsave(my_spin_lock, flags);
    list_add_tail(&req.list, &my_work_list);
    spin_unlock_irqrestore(my_spin_lock, flags);
    
    queue_work(my_wq, &my_work);
    
    return;
}


public.h

#ifndef __PUBLIC_H
#define __PUBLIC_H

#define uint8   unsigned char
#define uint16  unsigned short
#define uint32  unsigned int
#define uint64  unsigned long

#define DBG_PRINT printf    //定义自己的打印函数

extern void my_alloc(uint32 size)
{
    //自己定义内存申请函数
}

extern void my_free(char *)
{
    //自己定义内存释放函数
}
#endif //__PUBLIC_H



关于内核的内存管理可以参考另一篇博文:http://blog.csdn.net/wangyuling1234567890/article/details/17324171

posted @ 2014-03-19 23:38  菜鸟天空  阅读(290)  评论(0编辑  收藏  举报