博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记录些等待队列(wait_queue)的使用
阅读量:3556 次
发布时间:2019-05-20

本文共 2120 字,大约阅读时间需要 7 分钟。

贴几篇文章先...


记录些概念和接口。

1. 什么是睡眠?

cpu调度 有 按时间片轮转, 抢占式基于优先级, 实时调度等很多方式。

不同场景使用不同调度方式。

比如Linux就是一个非硬实时的, 抢占式基于优先级,  也按时间片轮转的调度系统。

VxWorks, Nuclues等为实时操作系统(RTOS)。

 

简单说, 线程被挂起, cpu去干别的事了,  该线程就算睡眠了...

 

 

2. 如何睡眠?

1).  被动睡眠, 比如时间片到了, cpu调度其他线程。irq中断来了, cpu去执行isr中断处理函数等。

2).  主动睡眠,  设置当前状态为TASK_INTERRUPTIBLE, 然后调用schedule()或者schedule_timeout()函数。

     会主动放弃cpu, 进入挂起状态。

 

3. 等待队列的使用场景?

1). 以IO操作为例, 用户态读写操作时, 如果内核态文件系统/驱动设备 不满足情况。通常会阻塞住这次IO调用。

即read, write需要等待设备/数据ready后, 才能读出,  写入数据。

内核态有几种实现方式, 

A. 循环判断设备状态/数据是否ready, ok后完成这次IO。 - 这样子就是白白浪费cpu了。

B. 直接返回-EAGAIN等错误,  让用户下次再来读写...

    这就是非阻塞式IO(但不是异步IO), 比如有些alsa 接口, snd_pcm_read, snd_pcm_write等等。都是非阻塞IO的情况。

    (这种有很多,  只要能返回-EAGAIN那种, 都是非阻塞IO)

C. 依然阻塞方式, 内核态可以使用等待队列的方式, 主动放弃cpu执行, 如此就能减低cpu负载了。


D. 顺便提一句异步IO, 即AIO, 所谓异步, 通常以注册回调函数的方式来实现。 即注册读写IO 到内核态, 当内核态有IO数据后, 

调用用户态的IO回调函数,  这就算异步IO。我也用的不多... 先暂时不管了...

E. 哦,  还有种poll, select, epoll这种, 是多路复用IO的接口,  通常一个设备IO即一个fd文件描述符的读写, 我们直接使用read, write函数阻塞等待就是了。 但如果用户态进程, 需要同时监听多个设备的IO, 一般来说就几种方式...

     (1) 起多进程, 或者多线程,  每个线程独立读写对应设备。 - 浪费...

     (2) 单个进程, 循环挨个读写设备....  - 浪费...

     (3) 多路复用IO, poll, select, epoll 一个文件描述符的数组, 当数组内的设备IO 准备就绪后, 在针对性地执行读写操作。 - 好办            法!


3. 如何使用等待队列?

差点又忘了正题,  关于如何使用等待队列。 内核中已经封装好一些接口。

1). 创建等待队列头部, 

DECLARE_WAIT_QUEUE_HEAD(name)

或者

wait_queue_head_t my_queue;

init_waitqueue_head(&my_queue);

 

2). 简单睡眠...

内核中定义了很多帮助宏, 创建完等待队列后, 简单使用以下宏就可以使当前线程挂起并进入等待队列。

wait_event(queue, condition)

wait_event_interruptible(queue, condition)

wait_event_timeout(queue, condition, timeout)

wait_event_interruptible_timeout(queue, condition, timeout)

 

*简单睡眠如何唤醒。两个宏

void wake_up(wait_queue_head_t *queue)

void wake_up_interruptible(wait_queue_head_t *queue)

 

3). 手动睡眠

稍微复杂点, 不用上面那些宏。

在第一步已经创建了等待队列头部,

A. 下面创建一个等待队列条目。

DECLARE_WAITQUEUE(name, task)

 

B. 将等待队列条目 放入等待队列中

void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)

void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)

void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)

 

C. 设置线程状态

set_current_state(TASK_INTERRUPTIBLE)

D. 进程调度

schedule() 或者 schedule_timeout()


关于内核中如何实现...后面看懂了继续。

 

总结一下:

如何使用等待队列,  简单明了:

1. 创建等待队列头部, 创建等待队列项目。

2. 将等待队列条目加入等待队列中。

3. 设置当前进程/线程状态。

4. 进程/线程调度。

转载地址:http://xpcrj.baihongyu.com/

你可能感兴趣的文章
CMake下载
查看>>
未调用fflush产生的图片文件无法打开问题
查看>>
SQL 约束(二)
查看>>
SQL ALTER用法(三)
查看>>
SQL where子句及查询条件语句(六)
查看>>
SQL 连接JOIN(九)
查看>>
linux VM虚拟机可以ping通主机,但主机无法ping通虚拟机
查看>>
linux 错误码
查看>>
C++ 中Struct与typedef struct总结
查看>>
WNetAddConnection2调用失败,错误码1200/1312
查看>>
POI读写Excel的基本使用
查看>>
淘宝网站的架构演进
查看>>
设置zookeeper开机自启动流程
查看>>
CentOS安装mysql5.7的教详细流程
查看>>
项目整合微信扫码登录功能
查看>>
分布式文件系统FastDfs的搭建
查看>>
Springboot项目利用Java客户端调用FastDFS
查看>>
全文检索工具elasticsearch的安装和简单介绍
查看>>
利用Kibana学习全文检索工具elasticsearch
查看>>
SpringBoot在Test测试类或自定义类中通过@Autowired注入为null
查看>>