linux 工作队列workqueue

===============================   博客点滴积累,部分话语和知识点来源于网络,感谢网络资源的提供者======


1 看一下内核创建内核工作线程的过程

start_kernel()

kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
kernel_init()
do_basic_setup()
init_workqueues();
hotcpu_notifier(workqueue_cpu_callback, 0);//注册到内核通知链
keventd_wq = create_workqueue("events");//每个cpu都会创建工作队列events线程


#define __create_workqueue(name, singlethread, freezeable)\
__create_workqueue_key((name), (singlethread), (freezeable), NULL, NULL)


__create_workqueue_key((name), (singlethread), (freezeable), NULL, NULL)
err = create_workqueue_thread(cwq, singlethread_cpu);
start_workqueue_thread(cwq, -1);
worker_thread()
run_workqueue()
struct work_struct *work = list_entry(cwq->worklist.next,struct work_struct, entry);//取链表元素
work_func_t f = work->func;
f(work);//用户注册的工作函数被调用

2 工作任务结构体

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; //函数指针,工作队列线程回调

};

用户接口schedule_work,将工作任务加入内核工作队列

int fastcall schedule_work(struct work_struct *work)
{
return queue_work(keventd_wq, work);
}

schedule_work
queue_work(struct workqueue_struct *wq, struct work_struct *work)
__queue_work(wq_per_cpu(wq, get_cpu()), work);
insert_work(cwq, work, 1); //链表插入

3延迟工作 ,也是通过工作队列 加定时器实现的

struct delayed_work {

struct work_struct work;

struct timer_list timer;

};

// 添加工作队列链表
int schedule_delayed_work_on(int cpu,
struct delayed_work *dwork, unsigned long delay)
{
return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
}
// 添加一个定时器
int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay)
{
int ret = 0;
struct timer_list *timer = &dwork->timer;
struct work_struct *work = &dwork->work;

if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
BUG_ON(timer_pending(timer));
BUG_ON(!list_empty(&work->entry));

/* This stores cwq for the moment, for the timer_fn */
set_wq_data(work, wq_per_cpu(wq, raw_smp_processor_id()));
timer->expires = jiffies + delay;
timer->data = (unsigned long)dwork;
timer->function = delayed_work_timer_fn; // 时间到了调用该函数,将work添加到工作队列

if (unlikely(cpu >= 0))
add_timer_on(timer, cpu);
else
add_timer(timer);
ret = 1;
}
return ret;
}
void delayed_work_timer_fn(unsigned long __data)
{
struct delayed_work *dwork = (struct delayed_work *)__data;
struct cpu_workqueue_struct *cwq = get_wq_data(&dwork->work);
struct workqueue_struct *wq = cwq->wq;
__queue_work(wq_per_cpu(wq, smp_processor_id()), &dwork->work);
}

你可能感兴趣的:(嵌入式Linux,linux,工作队列,workqueue)