linux wake_up 相关函数
来源:互联网 发布:淘宝充值平台能赚钱吗 编辑:程序博客网 时间:2024/06/05 23:52
linux 中有两种wake_up函数.第一种是wake_up_xxx,第二种是wake_up_interruptible_xxx.
1.wake_up_xxx 函数如下:
#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)#define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL)#define wake_up_all(x) __wake_up(x, TASK_NORMAL, 0, NULL)#define wake_up_locked(x) __wake_up_locked((x), TASK_NORMAL, 1)#define wake_up_all_locked(x) __wake_up_locked((x), TASK_NORMAL, 0)
TM被骗了,这不是函数,而是一堆宏.因为习惯问题,正文中我还是叫它们函数吧.
wake_up_xxx函数可以唤醒以下函数(或宏)导致的等待.
sleep_on(wait_queue_head_t *q)sleep_on_timeout(wait_queue_head_t *q, long timeout)wait_event(wq, condition)wait_event_timeout(wq, condition, timeout)
那么以上几个wake_up函数有什么区别呢?
本文假设你已经知道wake_up()函数是用来唤醒等待队列的.只是不清楚以上几个wake_up函数具体的区别.如是这样,见下文:
wake_up :只唤醒等待队列中第一个等待的线程.
wake_up_nr :唤醒等待队列中从队列头开始的nr个等待的线程.
wake_up_all :唤醒等待队列中所有等待的线程.
wake_up_locked :同wake_up(),区别在于此函数用于在调用此函数时,用户已经手动 spin_lock了此等待队列头的 lock,(这个函数存在的原因是同一个spin_lock在同一个线程中不能递归加锁.)
wake_up_all_locked :这个函数的作用我想聪明的你已经猜到了.
提外话1.wake_up想唤醒几个队列就唤醒几个,是如果实现的呢?
wake_up调用流程如下:
wake_up(x) ->__wake_up(x, TASK_NORMAL, 1, NULL)->__wake_up_common();
由上面的调用流程可知,wake_up最终会调用到__wake_up_common函数,而此函数的第三个参数就是指明需要唤醒此等待队列的多少个线程.见__wake_up_common函数的if break条件中用到了nr_exclusive。
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int wake_flags, void *key){ wait_queue_t *curr, *next; list_for_each_entry_safe(curr, next, &q->task_list, task_list) { unsigned flags = curr->flags; if (curr->func(curr, mode, wake_flags, key) && (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive) break; }}
提外话2.看起来wake_up_all是不是比wake_up要牛逼,因为wake_up_all可以唤醒这个等待队列上的所有等待线程,wake_up只能唤醒一个
非也。
第一、在我们自己创建工作队列的用法来看,90%的情况下,工作队列中只有一个等待的线程。(不信看内核源码)
第二、即使同时唤醒多个线程,由于CPU不够用,或唤醒的几个线程由于需要访问共享临界区资源,而最终只用一个线程能运行。
2.wake_up_interruptible_xxx 函数如下
#define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)#define wake_up_interruptible_nr(x, nr) __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL)#define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)#define wake_up_interruptible_sync(x) __wake_up_sync((x), TASK_INTERRUPTIBLE, 1)
对应的,wake_up_interruptible_xxx函数可以唤醒以下函数(或宏)导致的等待
interruptible_sleep_on(wait_queue_head_t *q)interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)wait_event_interruptible(wq, condition)wait_event_interruptible_timeout(wq, condition, timeout)
发现没,wake_up唤醒wait_event,wake_up_interruptible唤醒wait_event_interruptible,这也许就是linux中的对称美。
wake_up_interruptible_xxx函数与wake_up_xxx函数功能类似。
只是wait_event_xxx与sleep_on_xxx函数进入等待队列后,不能被信号唤醒.
而wait_event_interruptible_xxx 与interruptible_sleep_on_xxx函数进入等待队列后,可以被信号唤醒。
题外话3. 既然等等了为什么还要唤醒,是什么信号唤醒它
这个问题曾经困扰了我好久,直到这几天看了网上以下这篇文章才焕然大悟。
(signal_pending函数解析)http://blog.csdn.net/tommy_wxie/article/details/12448935#
我的理解是:
1、当驱动正在执行一个阻塞操作时,如果不能被信号唤醒那么,这个时候用户按下ctrl+c将无法结束程序。
而如果是可唤醒的阻塞,则当用户按下ctrl+c,或向这个进程发送了一个信号时,内核会退出阻塞,先处理用户的信号响应。如果这时是在系统调用过程中阻塞,则当处理完信号响应后,系统会再次调用此系统调用。所以我们才会在驱动中看到可被interruptible的等待函数中在阻塞退出后,会执行如下代码。
这段代码就是在检查此次退出阻塞是因为有人wake_up了还是有信号需要到来需要处理。
当signal_pending(current)返回为true时,表示是有信号需要处理。
if (signal_pending(current)) { ret = -ERESTARTSYS; return ret; }
题外话4.为什么将sleep_on_xxx,与wait_event_xxx函数发在一起
原因我认为他们有以下几个共同点:
1、都是在一个自定义的等待队列头上等待,也都是通过这个等待队列来唤醒进程。
2、使用时用户只需要定义等待队列头wait_queue_head_t,而不需要定义等待队列wait_queue_t。等待队列由函数内部自己实现。
- linux wake_up 相关函数
- linux wake_up
- linux内核中等待队列 (函数wait_event与wake_up)
- linux 等待队列 wait_event wake_up等函数讲解
- linux内核中等待队列 (函数wait_event与wake_up)
- linux内核中等待队列 (函数wait_event与wake_up)
- linux内核中等待队列 (函数wait_event与wake_up)
- linux内核中等待队列 (函数wait_event与wake_up)
- linux内核中等待队列 (函数wait_event与wake_up)
- linux wait_event and wake_up
- linux-011中休眠函数以及唤醒函数的分析(sleep_on,wake_up)
- linux同步机制之wait_event和wake_up
- linux等待队列之wait_event和wake_up
- linux同步机制之wait_event和wake_up
- linux内核中等待队列(wait_event,wake_up...)
- linux内核中等待队列(wait_event,wake_up...)
- linux内核中等待队列(wait_event,wake_up...)
- linux内核中等待队列(wait_event,wake_up...)
- WebVie Posturl方式网页不正常问题解决
- Java语言规范基于JavaSE9 第七章 包和模块(六)
- 关于数据库你需要知道的基础知识
- 【Redis】Linux部署单个redis-3.0.6服务,实现开机启动,注册服务
- Elasticsearch 6.0.0 安装问题
- linux wake_up 相关函数
- 用new操作符创建函数的过程发生了什么
- java.util.NoSuchElementException
- [ResNet]系列 SENet
- angular的下拉表单
- ubuntu升级系统内核
- 在Android Studio中集成Zxing
- 正则表达式appendReplacement appendTail组合使用
- 【Ray Tracing in One Weekend】(ch6)Ray Tracer 里的反走样