rk3188--12.linux内核中工作队列的实现
2016-06-13 17:19
701 查看
两个结构体
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
};
struct workqueue_struct {
unsigned int flags;
union {
struct cpu_workqueue_struct __percpu *pcpu;
struct cpu_workqueue_struct *single;
unsigned long v;
} cpu_wq;
struct list_head list;
};
工作队列的使用步骤如下:
//0.首先定义两个结构体:
struct work_struct my_work;
struct workqueue_struct *my_work_queue;
//1.填充一个work_struct
INIT_WORK(&my_work, my_work_process);
//2.显式的创建一个工作队列
my_work_queue = create_workqueue(“my_work”);
//3.将工作提交到工作队列
queue_work(my_work_queue, &my_work);
//4. 调用工作队列处理函数
my_work_process(struct work_struct *work)
填充一个work_struct
即:
展开后:
__init_work(my_work, 0);
my_work->data = (atomic_long_t) WORK_DATA_INIT();
INIT_LIST_HEAD(&my_work->entry);
PREPARE_WORK(my_work, my_work_process);
显式的创建一个工作队列
create_workqueue 与 create_singlethread_workqueue都是调用了alloc_workqueue
struct workqueue_struct *__alloc_workqueue_key(const char *name,unsigned int flags, int max_active, struct lock_class_key *key, const char *lock_name)
{
struct workqueue_struct *wq;
unsigned int cpu;
}
EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
};
struct workqueue_struct {
unsigned int flags;
union {
struct cpu_workqueue_struct __percpu *pcpu;
struct cpu_workqueue_struct *single;
unsigned long v;
} cpu_wq;
struct list_head list;
struct mutex flush_mutex; int work_color; int flush_color; atomic_t nr_cwqs_to_flush; struct wq_flusher *first_flusher; struct list_head flusher_queue; struct list_head flusher_overflow; mayday_mask_t mayday_mask; struct worker *rescuer; int saved_max_active; const char *name;
};
工作队列的使用步骤如下:
//0.首先定义两个结构体:
struct work_struct my_work;
struct workqueue_struct *my_work_queue;
//1.填充一个work_struct
INIT_WORK(&my_work, my_work_process);
//2.显式的创建一个工作队列
my_work_queue = create_workqueue(“my_work”);
//3.将工作提交到工作队列
queue_work(my_work_queue, &my_work);
//4. 调用工作队列处理函数
my_work_process(struct work_struct *work)
填充一个work_struct
define INIT_WORK(_work, _func) \
do { \ __INIT_WORK((_work), (_func), 0); \ } while (0)
即:
define __INIT_WORK(_work, _func, _onstack) \
do { \ __init_work((_work), _onstack); \ (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ INIT_LIST_HEAD(&(_work)->entry); \ PREPARE_WORK((_work), (_func)); \ } while (0)
展开后:
__init_work(my_work, 0);
my_work->data = (atomic_long_t) WORK_DATA_INIT();
INIT_LIST_HEAD(&my_work->entry);
PREPARE_WORK(my_work, my_work_process);
显式的创建一个工作队列
define create_workqueue(name) \
alloc_workqueue((name), WQ_MEM_RECLAIM, 1)
define create_freezable_workqueue(name) \
alloc_workqueue((name), WQ_FREEZABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
define create_singlethread_workqueue(name) \
alloc_workqueue((name), WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
create_workqueue 与 create_singlethread_workqueue都是调用了alloc_workqueue
define alloc_workqueue(name, flags, max_active) \
__alloc_workqueue_key((name), (flags), (max_active), NULL, NULL)
struct workqueue_struct *__alloc_workqueue_key(const char *name,unsigned int flags, int max_active, struct lock_class_key *key, const char *lock_name)
{
struct workqueue_struct *wq;
unsigned int cpu;
if (flags & WQ_MEM_RECLAIM) flags |= WQ_RESCUER; if (flags & WQ_UNBOUND) flags |= WQ_HIGHPRI; max_active = max_active ?: WQ_DFL_ACTIVE; max_active = wq_clamp_max_active(max_active, flags, name); wq = kzalloc(sizeof(*wq), GFP_KERNEL); wq->flags = flags; wq->saved_max_active = max_active; mutex_init(&wq->flush_mutex); atomic_set(&wq->nr_cwqs_to_flush, 0); INIT_LIST_HEAD(&wq->flusher_queue); INIT_LIST_HEAD(&wq->flusher_overflow); wq->name = name; lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); INIT_LIST_HEAD(&wq->list); alloc_cwqs(wq); for_each_cwq_cpu(cpu, wq) { struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); struct global_cwq *gcwq = get_gcwq(cpu); cwq->gcwq = gcwq; cwq->wq = wq; cwq->flush_color = -1; cwq->max_active = max_active; INIT_LIST_HEAD(&cwq->delayed_works); } if (flags & WQ_RESCUER) { struct worker *rescuer; alloc_mayday_mask(&wq->mayday_mask, GFP_KERNEL); wq->rescuer = rescuer = alloc_worker(); rescuer->task = kthread_create(rescuer_thread, wq, "%s", name); rescuer->task->flags |= PF_THREAD_BOUND; wake_up_process(rescuer->task); } spin_lock(&workqueue_lock); if (workqueue_freezing && wq->flags & WQ_FREEZABLE) for_each_cwq_cpu(cpu, wq) get_cwq(cpu, wq)->max_active = 0; list_add(&wq->list, &workqueues); spin_unlock(&workqueue_lock); return wq;
}
EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
相关文章推荐
- Linux日志文件总管――logrotate
- 字符设备驱动相关内容
- linux 变量设置
- linux cntlm代理的配置
- CentOS 6.5下Samba服务器的安装与配置
- linux基础命令
- could not bind listening IPv4 socket错误
- linux工具---windows文件传输到linux工具以及SSH客户端软件
- linux工具---windows文件传输到linux工具以及SSH客户端软件
- Linux系统常用指令、管道(pipe)、文件查找(find)
- Semi-Automatic 3D Annotation3D源码编译过程记录
- linux下开发android_jni过程及错误经历
- linux IIC子系统分析(八)——实例分析通过sysfs访问I2c设备
- linux IIC子系统分析(七)——实例分析通过i2c-dev操作I2C设备
- linux基本命令
- linux IIC子系统分析(六)——I2c plaform driver 初始化
- linux IIC子系统分析(五)——I2C plaform device 初始化
- linux IIC子系统分析(四)——I2c bus初始化
- Linux防火墙的配置方法(firewalld服务)
- Linux系统Root密码破解(RHEL7&Centos7版本)