技术标签: completion Linux内核 Linux linux
在内核编程中常有这样的场景,在当前线程中创建一个线程,并且等待它完成之后再继续执行。通常可以用信号量来解决它,也可以用completion机制来解决。
使用completion比使用信号量简单。
使用completion可以一次性唤醒所有等待进程,而用信号量会比较麻烦。
The basic summary is that we had this (fairly common) way of waiting for certain events by having a locked semaphore on the stack of the waiter, and then having the waiter do a "down()" which caused it to block until the thing it was waiting for did an "up()".
This works fairly well, but it has a really small (and quite unlikely) race on SMP, that is not so much a race of the idea itself, as of the implementation of the semaphores. We could have fixed the semaphores, but there were a few reasons not to:
CompletionsA common pattern in kernel programming involves initiating some activity outside of the current thread, then waiting for that activity to complete. This activity can be the creation of a new kernel thread or user-space process, a request to an existing process, or some sort of hardware-based action. It such cases, it can be tempting to use a semaphore for synchronization of the two tasks, with code such as: struct semaphore sem; init_MUTEX_LOCKED(&sem); start_external_task(&sem); down(&sem); The external task can then call up(&sem) when its work is done. As is turns out, semaphores are not the best tool to use in this situation. In normal use, code attempting to lock a semaphore finds that semaphore available almost all the time; if there is significant contention for the semaphore, performance suffers and the locking scheme needs to be reviewed. So semaphores have been heavily optimized for the "available" case. When used to communicate task completion in the way shown above, however, the thread calling down will almost always have to wait; performance will suffer accordingly. Semaphores can also be subject to a (difficult) race condition when used in this way if they are declared as automatic variables. In some cases, the semaphore could vanish before the process calling up is finished with it. |
/*
* Completions 目前使用先进先出的队列来存放等待‘completion’的事件
*/
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
(1) 定义completion
struct completion my_completion;
(2) 初始化completion
init_completion(&my_completion);/*动态创建一个completion*/
DECLEARE_COMPLETION(my_completion);/*(包含定义)静态初始化completion*/
(3) 等待completion
/*This waits to be signaled for completion of a specific task. It is NOT interruptible and there is no timeout.*/
void wait_for_completion(struct completion *c);
/*This waits for completion of a specific task to be signaled. It is interruptible.*/
int wait_for_completion_interruptible(struct completion *x);
/*This waits to be signaled for completion of a specific task. It can be
* interrupted by a kill signal.
*/
int wait_for_completion_killable(struct completion *x);
/*This waits for either a completion of a specific task to be signaled or for a
* specified timeout to expire. The timeout is in jiffies. It is not
* interruptible.
*/
unsigned long wait_for_completion_timeout(struct completion *x,
unsigned long timeout);
/** This waits for either a completion of a specific task to be signaled or for a
* specified timeout to expire. It is interruptible. The timeout is in jiffies.
*/
long wait_for_completion_interruptible_timeout(
struct completion *x, unsigned long timeout);
/*This waits for either a completion of a specific task to be
* signaled or for a specified timeout to expire. It can be
* interrupted by a kill signal. The timeout is in jiffies.
*/
long wait_for_completion_killable_timeout(
struct completion *x, unsigned long timeout);
(4) 唤醒completion
void complete(struct completion *c);/*唤醒一个等待的Thread*/
void complete_all(struct completion *c);/*唤醒所有等待此completion的Threads*/
[1] http://stackoverflow.com/questions/4764945/difference-between-completion-variables-and-semaphores
需求:我们需要把线上日志收集起来进行分析。在开发阶段,更多的时候程序是运行在本地,所以使用FileBeats就有点繁琐。我们采用直接将日志通过tcp输出到logstash的方案。同时,我们的日志并没有统一的格式,按照日志分析的需求格式都不一样。比如我们需要监控http请求的日志,监控websocket对话的日志,监控搜索gu关键词的日志等等。这就需要我们需要根据不同的需求制定各自的格式,然后分开输出到ES数据库。一、安装ELK这里对此不作过多讲解。es我使用的是docker版本,logstash
之前用Python做了一个通道号查找的小程序,只不过没有做界面。最近的一个项目要用到帧校验(CS),为了方便,写了一个计算的小程序。该程序用了QT4来做界面,也算是我的第一个QT小程序。现在来分享一下编写过程中的心得体会,以及遇到的坑。Python的环境是2.7。CS校验和的C代码如下:/*******************
<preview type="" 过渡全景图的类型 url="previewpano.jpg" 过渡全景图路径 striporder="LFRBUD" 定义图像顺序 details="16" 图像细节质量调整,越大越清晰 />...
NoSQL数据库 MongoDB数据库是一种NoSQL数据库,NoSQL数据库不是这几年才有的,从数据库的初期发展就已经有了NoSQL数据库。数据库之中支持的SQL语句是由IBM开发出来的,并且最早就应用在了Orcale数据库,但是SQL语句的使用并不麻烦,就是简单的几个关键字:SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。但是这个时候有人开始反感
解决(部分) 2019款macbookpro -16寸 外接显示器风扇不停的转,温度特别高作者:Quan Chen链接:https://www.zhihu.com/question/290208585/answer/1768740672来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。发热很久了,最后找到一个解决方法。禁止独显,使用集显即可。但设置仅使用集显后还需要在关闭系统设置/电源/自动切换显卡 选项,不然外接显示器没有反应。步骤:打开终端,输入:sudo pmse
效果:原理:1.在保存数据的时候就需要记录当前数据条目的时戳,我是按照1970-01-01 08:00:00为起始时间点,计算当前时间离这个起始时间一共是多少毫秒,如下:QDateTime origin_time = QDateTime::fromString("1970-01-01 08:00:00","yyyy-MM-dd hh:mm:ss");QDateTime current_t...
MySQL 5.1 中,在复制方面的改进就是引进了新的复制技术:基于行的复制。简言之,这种新技术就是关注表中发生变化的记录,而非以前的照抄 binlog 模式。从 MySQL 5.1.12 开始,可以用以下三种模式来实现:基于SQL语句的复制(statement-based replication, SBR),基于行的复制(row-based replication, RBR),混合模式复制(
一、引言现在已经是十月份的月末了,金九银十,这个找工作和面试的热潮已经渐渐退隐。潮涨潮退,有的人从里面收获了心仪的offer;有的人走了一趟,一无所获,或者收获寥寥,无甚满意;还有的人在观望,等待下一个良机。这里分析一波现在的面试行情,带大家了解一下自己所处的位置,另外,分享一下有用的资料,帮助大家提升自己的战斗力。从初中级到高级,移动端程序员的进阶宝典想要成为一名优秀的Android开发,你需要一份完备的 知识体系,在这里,让我们一起成长为自己所想的那样。下面我们就以 Android 开发为
双序列全局比对主要是依据Needleman-Wnnsch算法来进行整个过程分为三步1.设置一个矩阵:第一条序列长m,沿x轴排列,第二条序列长n,沿y轴排列2.设置打分矩阵,根据适当的打分公式来对对应的碱基进行打分,有四种情况:1.两碱基完全匹配2.不匹配3.第一条序列引入空位4.第二条序列引入空位3.反向寻找最佳比对,通过回溯法,从打分矩阵的右下方最大得分处,往左上方寻找最大值。所谓动态规划表示最...
了解视频图像数据的基础
小白想用安卓上传图片到七牛,先用java试了下,但一直抛出异常,下面是我代码,后面给出异常信息import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;impo...
Qt核心元对象系统动态投射这样投射是失败的,返回指针label为NULL,因为QMyWidget不是QLabel的子类。使用动态投射,使得程序可以在运行时对不同的对象做不同的处理。属性系统两个宏Q_PROPERTY(),基于元对象系统实现。Qt的属性系统与C++编译器无关,可以用任何标准的C++编译器编译定义了属性的Qt C++程序Q_CLASSINFO(),可以为类的元对象...