工作队列

工作队列是一种将工作推后执行的机制。
工作队列可以把工作推后,交由一个内核线程去执行,它是中断下半部分实现的一种形式,
而且它总是会在进程上下文中执行。这样,通过工作队列执行的代码能占尽进程上下文的所有优势。
最重要的就是工作队列允许重新调度甚至是睡眠。

工作的结构体声明
typedef void (*work_func_t)(struct work_struct *work);


struct work_struct {
	atomic_long_t data;
#define WORK_STRUCT_PENDING 0		/* T if work item pending execution */
#define WORK_STRUCT_FLAG_MASK (3UL)
#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
	struct list_head entry;
	work_func_t func;
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};


#define WORK_DATA_INIT()	ATOMIC_LONG_INIT(0)


struct delayed_work {
	struct work_struct work;
	struct timer_list timer;
};

定义并初始化一个工作
#define DECLARE_WORK(n, f)					\
	struct work_struct n = __WORK_INITIALIZER(n, f)


#define __WORK_INITIALIZER(n, f) {				\
	.data = WORK_DATA_INIT(),				\
	.entry	= { &(n).entry, &(n).entry },			\
	.func = (f),						\
	__WORK_INIT_LOCKDEP_MAP(#n, &(n))			\
	}


定义并初始化一个延迟的工作
#define DECLARE_DELAYED_WORK(n, f)				\
	struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)


#define __DELAYED_WORK_INITIALIZER(n, f) {			\
	.work = __WORK_INITIALIZER((n).work, (f)),		\
	.timer = TIMER_INITIALIZER(NULL, 0, 0),			\
	}

不定义仅初始化一个工作
#define INIT_WORK(_work, _func)						\
	do {								\
		(_work)->data = (atomic_long_t) WORK_DATA_INIT();	\
		INIT_LIST_HEAD(&(_work)->entry);			\
		PREPARE_WORK((_work), (_func));				\
	} while (0)

不定义仅初始化一个延迟的工作
#define INIT_DELAYED_WORK(_work, _func)				\
	do {							\
		INIT_WORK(&(_work)->work, (_func));		\
		init_timer(&(_work)->timer);			\
	} while (0)
/*
 * initialize a work item's function pointer
 */
#define PREPARE_WORK(_work, _func)				\
	do {							\
		(_work)->func = (_func);			\
	} while (0)


#define PREPARE_DELAYED_WORK(_work, _func)			\
	PREPARE_WORK(&(_work)->work, (_func))

工作队列的结构体

struct workqueue_struct {
	struct cpu_workqueue_struct *cpu_wq;
	struct list_head list;
	const char *name;
	int singlethread;
	int freezeable;		/* Freeze threads during suspend */
	int rt;
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};

/*
 * The per-CPU workqueue (if single thread, we always use the first
 * possible cpu).
 */
struct cpu_workqueue_struct {

	spinlock_t lock;

	struct list_head worklist;
	wait_queue_head_t more_work;
	struct work_struct *current_work;

	struct workqueue_struct *wq;
	struct task_struct *thread;
} ____cacheline_aligned;


创建一个工作队列
#define create_workqueue(name) __create_workqueue((name), 0, 0, 0)
该函数会创建一个内核线程,该线程的名称就是传递的参数name;另外还会返回一个
动态创建的工作队列的指针;最后让该线程进行起来。

/**
 * schedule_work - put work task in global workqueue
 * @work: job to be done
 *
 * Returns zero if @work was already on the kernel-global workqueue and
 * non-zero otherwise.
 *
 * This puts a job in the kernel-global workqueue if it was not already
 * queued and leaves it in the same position on the kernel-global
 * workqueue otherwise.
 * 这将把一个工作加入到内核全局变量工作队列中,如果没有加入成功,那么将在
 * 相同的地方leaves it.
 */
 
static struct workqueue_struct *keventd_wq;


int schedule_work(struct work_struct *work)
{
	return queue_work(keventd_wq, work);
}
说明:
该函数将工作[work]加入到全局的工作队列[keventd_wq]中。
如果成功返回0,否则返回非0;

/**
 * schedule_delayed_work - put work task in global workqueue after delay
 * @dwork: job to be done
 * @delay: number of jiffies to wait or 0 for immediate execution
 *
 * After waiting for a given time this puts a job in the kernel-global
 * workqueue.
 */
int schedule_delayed_work(struct delayed_work *dwork,
					unsigned long delay)
{
	return queue_delayed_work(keventd_wq, dwork, delay);
}
说明:
该函数将延迟delay长的时间后再把工作[work]加入到全局的工作队列[keventd_wq]中。
@dwork: 将要加入的工作
@delay: 延迟的时间,如果为0表示不延迟,立即运行


总结:
工作队列的用法:
1> 定义并初始化一个工作,可以用以下两个方法:
a) DECLARE_WORK(n, f)

b) INIT_WORK(_work, _func)


       e.g.      DECLARE_WORK (zwmy_work, zwmy_test_func);

2> 如果用内核初始化好的工作者线程的话,那么只需要调用下面这个函数:

       schedule_work(struct work_struct *work);

e.g.     schedule_work(&zwmy_work);

   
3> 如果需要自定义一个工作者线程的话,那么:
   a) 调用下面的函数创建一个工作者线程,创建一个工作队列

 create_workqueue(name)

e.g. struct workqueue_struct * zwmy_wq;

zwmy_wq = create_workqueue(&zwmy_work);

   b) 调用下面的函数将工作加入到工作队列中

queue_work(struct workqueue_struct *wq, struct work_struct *work);

        e.g.      queue_work(zwmy_wq,  &zwmy_work);




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值