linux系统工作队列
来源:互联网 发布:淘宝卖家用淘客推广 编辑:程序博客网 时间:2024/04/29 04:32
最近一直再调试一个基于spi的打印机,一路心酸坎坷啊。
在这个打印的驱动中,需要不断读取打印数据写入spi,在时序方面要达到每1ms往spi写入一次数据,所以用到了工作队列以及定时器来实现。
1、工作队列
工作队列提供一个通用的办法将任务延迟到 bottom halves。处于核心的是工作队列(结构体 workqueue_struct
), 任务被安排到该结构体当中。任务由结构体 work_struct
来说明,用来鉴别哪些任务被延迟以及使用哪个延迟函数。 events/X
内核线程(每 CPU 一个)从工作队列中抽取任务并激活一个 bottom-half 处理程序(由处理程序函数在结构体 work_struct
中指定)。
struct
work_struct {
unsigned
long
pending;
struct
list_head entry;
void
(*func)(
void
*);
void
*data;
void
*wq_data;
struct
timer_list timer;
};
pending是用来记录工作是否已经挂在队列上;
entry是循环链表结构;
func作为函数指针,由用户实现;
data用来存储用户的私人数据,此数据即是func的参数;
wq_data一般用来指向工作者线程(工作者线程参考下文);
timer是推后执行的定时器。
work_struct的这些变量里,func和data是用户使用的,其他是内部变量,我们可以不用太过关心。
API:
INIT_WORK(_work, _func, _data);
int
schedule_work(
struct
work_struct *work);
int
schedule_delayed_work(
struct
work_struct *work, unsigned
long
delay);
void
flush_scheduled_work(
void
);
int
cancel_delayed_work(
struct
work_struct *work);
1、初始化指定工作,目的是把用户指定的函数_func及_func需要的参数_data赋给work_struct的func及data变量。
2、对工作进行调度,即把给定工作的处理函数提交给缺省的工作队列和工作者线程。工作者线程本质上是一个普通的内核线程,在默认情况下,每个CPU均有一个类型为“events”的工作者线程,当调用schedule_work时,这个工作者线程会被唤醒去执行工作链表上的所有工作。
3、延迟执行工作,与schedule_work类似。
4、刷新缺省工作队列。此函数会一直等待,直到队列中的所有工作都被执行。
5、flush_scheduled_work并不取消任何延迟执行的工作,因此,如果要取消延迟工作,应该调用cancel_delayed_work。
以上均是采用缺省工作者线程来实现工作队列,其优点是简单易用,缺点是如果缺省工作队列负载太重,执行效率会很低,这就需要我们创建自己的工作者线程和工作队列。
API:
struct
workqueue_struct *create_workqueue(
const
char
*name);
int
queue_work(
struct
workqueue_struct *wq,
struct
work_struct *work);
int
queue_delayed_work(
struct
workqueue_struct *wq,
struct
work_struct *work, unsigned
long
delay);
void
flush_workqueue(
struct
workqueue_struct *wq);
void
destroy_workqueue(
struct
workqueue_struct *wq);
1、创建新的工作队列和相应的工作者线程,name用于该内核线程的命名。
2、类似于schedule_work,区别在于queue_work把给定工作提交给创建的工作队列wq而不是缺省队列。
3、延迟执行工作。
4、刷新指定工作队列。
5、释放创建的工作队列。
下面一段代码可以看作一个简单的实作:
1.创建工作队列并与工作任务函数绑定:
struct delayed_work ms_queue_work;
struct workqueue_struct *ms_wqueue; ms_wqueue = create_rt_workqueue("1ms");INIT_DELAYED_WORK(&ms_queue_work, queue_work_task);if (!ms_wqueue) {pr_err("failed to create workqueue\n");return -1;}
工作队列的使用有两个办法,一是使用系统默认的工作队列,它对应一个默认的工作者线程,这个线程是什么策略我没有查过,应该是SCHED_NORMAL ,第二种方法就是自己创建一个队列
#define create_workqueue(name) __create_workqueue((name), 0, 0, 0)#define create_rt_workqueue(name) __create_workqueue((name), 0, 0, 1)#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1, 0)#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0, 0)</span>这里的create_rt_workqueue是为了创建一个调度策略为SCHED_FIFO的工作队列。
2.延时调度:
queue_delayed_work(ms_wqueue, &ms_queue_work, 1 );schedule_delayed_work(&ms_queue_work,usecs_to_jiffies(1000));
以上2个函数都可以实现延时调度,第一个是指一个时钟节拍执行一次,一个节拍即1/HZ 的时间,默认值是100,可以在arch/arm/KConfig里面将默认值改成1000,这样时钟节拍就变成了1ms,如无需要还是建议不要去修改这个值。如果要循环调度,则需要每次都调用一次延时调度函数。
- linux系统工作队列
- Linux中的工作队列
- Linux中的工作队列
- Linux中的工作队列
- linux工作队列
- Linux 工作队列
- linux kernel 工作队列
- Linux中的工作队列
- Linux 工作队列
- linux kernel 工作队列
- Linux中的工作队列
- Linux中的工作队列
- linux工作队列编程
- linux 工作队列
- linux工作队列
- Linux中的工作队列
- Linux 工作队列
- linux kernel 工作队列
- windows下查找一个目录下所有文件内容
- storyboard中关于拉伸压缩的优先级priority的设置(自适应布局很有用)
- 登录超时 (1440 秒未活动),请重新登录。 phpmyadmin
- Web开发中需要了解的东西
- xcode6 模拟器不能使用以及 不显示键盘
- linux系统工作队列
- h264—CABAC算法原理简介1
- vs2008试用到期后解决办法
- jdk与tomcat安装配置环境,与如何关联,如何建立起一个新的项目
- 堆和栈的区别 java
- DevExpress_XRTable Report 绑定数据,分页打印
- iptables详解
- EBS待定资源事物处理
- UltraEdit如何激活