linux 同步机制之complete【转】

转自: http://blog.csdn.net/wealoong/article/details/8490654

Linux内核中,completion是一种简单的同步机制,标志"things may proceed"。

要使用completion,必须在文件中包含<linux/completion.h>,同时创建一个类型为struct completion的变量。

[cpp] view plain copy

 

  1. 这个变量可以静态地声明和初始化:  
  2. DECLARE_COMPLETION(my_comp);  
  3. 或者动态初始化:  
  4. struct completion my_comp;  
  5. init_completion(&my_comp);  

如果驱动程序要在执行后面操作之前等待某个过程的完成,它可以调用wait_for_completion ,以要完成的事件为参数:

[html] view plain copy

 

  1. void wait_for_completion(struct completion *comp);  

wait_for_completion等待在completion上。如果加了interruptible,就表示线程等待可被外部发来的信号打断;如果加了killable,就表示线程只可被kill信号打断;如果加了timeout,表示等待超出一定时间会自动结束等待,timeout的单位是系统所用的时间片jiffies(多为1ms)。

如果其它部分代码可以确定事件已经完成,可以调用下面两个函数之一来唤醒等待该事件的进程:

[cpp] view plain copy

 

  1. void complete(struct completion *comp);  
  2. void complete_all(struct completion *comp); /* Linux 2.5.x以上版本 */  

前一个函数将只唤醒一个等待进程,而后一个函数唤醒等待该事件的所以进程。由于completion的实现方式,即使complete在wait_for_competion之前调用,也可以正常工作。
例如,在MD设备驱动程序实现中,有一个恢复线程md_recovery_thread。驱动程序通过md_register_thread和md_unregister_thread来注册和注销恢复线程。恢复线程的执行逻辑在md_thread函数中,大致如下:

[cpp] view plain copy

 

  1. int md_thread(void * arg)  
  2. {  
  3.     线程初始化;  
  4.     while (运行) {  
  5.         处理逻辑;  
  6.         接收信号;  
  7.     }  
  8.     return 0;  
  9. }  

md_register_thread将创建一个恢复线程,它必须在线程真正初始化结束之后才能返回该线程的指针。因此,其逻辑是:

[cpp] view plain copy

 

  1. mdk_thread_t *md_register_thread(void (*run) (void *), void *data, const char *name)  
  2. {  
  3.     mdk_thread_t *thread;  
  4.     ……  
  5.     struct completion event;  
  6.     /* 为线程分配空间 */  
  7.     thread = (mdk_thread_t *) kmalloc (sizeof(mdk_thread_t), GFP_KERNEL);  
  8.     ……  
  9.     init_completion(&event);  
  10.     ……  
  11.     thread->event = &event;  
  12.     /* 创建内核线程 */  
  13.     ret = kernel_thread(md_thread, thread, 0);  
  14.     /* 等待线程初始化结束 */  
  15.     ……  
  16.     wait_for_completion(&event);  
  17.     /* 返回线程指针 */  
  18.     return thread;  
  19. }  

而md_unregister_thread通过向线程发送SIGKILL信号注销恢复线程,它也需要在线程真正退出后才能释放线程所占用的内存。因此,其逻辑是:

[cpp] view plain copy

 

  1. void md_unregister_thread(mdk_thread_t *thread)  
  2. {  
  3.     struct completion event;  
  4.     init_completion(&event);  
  5.     thread->event = &event;  
  6.     ……  
  7.     /* 向线程发送SIGKILL信号终止其运行 */  
  8.     md_interrupt_thread(thread);  
  9.     /* 等待线程退出 */  
  10.     wait_for_completion(&event);  
  11.     /* 释放线程所占用的内存 */  
  12.     kfree(thread);  
  13. }  

如果考虑completion,md_thread的逻辑是:

[cpp] view plain copy

 

  1. int md_thread(void * arg)  
  2. {  
  3.     线程初始化;  
  4.     complete(thread->event);   
  5.     while (运行) {  
  6.         处理逻辑;  
  7.         接收信号;  
  8.     }  
  9.     complete(thread->event);   
  10.     return 0;  
  11. }  

需要说明的是,由于等待事件是在驱动程序和恢复线程中的一个共享资源,它必须是一个全局变量,或者如实现代码中,定义为一个局部变量,而将其指针放在恢复线程结构中。
typedef struct mdk_thread_s {
    ……
    struct completion *event;
    ……
} mdk_thread_t;

 

 

时间: 2024-09-20 09:02:40

linux 同步机制之complete【转】的相关文章

Linux网络文件系统的数据备份、恢复及同步机制

本文将详细介绍针对该网络文件系统的数据备份.恢复及同步机制在内核的具体实现,给广大系统管理员和研发人员提供技术参考.网络文件系统(NFS)协议是由 Sun MicroSystem 公司在 20 世纪 80 年代为了提供对共享文件的远程访问而设计和实现的,它采用了经典的客户机/服务器模式提供服务.为了达到如同 NFS 协议通过使用 Sun 公司开发的远在本机上使用本地文件系统一样便捷的效果,NFS 通过使用远程过程调用协议(RPC Protocol)来实现运行在一台计算机上的程序来调用在另一台远程

Linux内核同步机制之(四):spin lock【转】

转自:http://www.wowotech.net/kernel_synchronization/spinlock.html 一.前言 在linux kernel的实现中,经常会遇到这样的场景:共享数据被中断上下文和进程上下文访问,该如何保护呢?如果只有进程上下文的访问,那么可以考虑使用semaphore或者mutex的锁机制,但是现在中断上下文也参和进来,那些可以导致睡眠的lock就不能使用了,这时候,可以考虑使用spin lock.本文主要介绍了linux kernel中的spin loc

Linux之同步机制(信号量,自旋锁)

当我们有两个open函数同时打开同一个设别节点的时候该怎么处理,我们肯定是不希望在同一时刻有两个应用程序都打开了这个驱动,这个时候我们可以才需一些措施. 同一时刻只能够打开一个设备节点,如何实现同一时刻只能有一个进程使用某个设备?使用linux互斥机制 Linux互斥机制有哪些? 答:有很多种,如:原子变量.互斥锁.信号量.自旋锁.读写锁等等 注意以上的集中互斥机制我只会讲解原子变量,信号量. 上一篇文章的链接:http://blog.csdn.net/qq_21792169/article/d

MySQL · 引擎特性 · InnoDB 同步机制

前言 现代操作系统以及硬件基本都支持并发程序,而在并发程序设计中,各个进程或者线程需要对公共变量的访问加以制约,此外,不同的进程或者线程需要协同工作以完成特征的任务,这就需要一套完善的同步机制,在Linux内核中有相应的技术实现,包括原子操作,信号量,互斥锁,自旋锁,读写锁等.InnoDB考虑到效率和监控两方面的原因,实现了一套独有的同步机制,提供给其他模块调用.本文的分析默认基于MySQL 5.6,CentOS 6,gcc 4.8,其他版本的信息会另行指出. 基础知识 同步机制对于其他数据库模

Linux Namespace机制简介

最近Docker技术越来越受到关注,作为Docker中很重要的一项技术,Namespace也就经常在Docker的简介里面看到. 在这里总结一下它的内部机制.也解决一下自己原来的一些疑惑. Namespace是什么: C++中的Namespace: 首先,先提一下Namespace是什么.最早知道这个名词是在学习C++语言的时候.由于现在的系统越来越复杂,代码中不同的模块就可能使用相同变量,于是就出现了Namespace,来对全局作用域进行划分. 比如C++的标注库都定义在STD Namespa

8天玩转并行开发——第五天 同步机制(下)

         承接上一篇,我们继续说下.net4.0中的同步机制,是的,当出现了并行计算的时候,轻量级别的同步机制应运而生,在信号量这一块 出现了一系列的轻量级,今天继续介绍下面的3个信号量 CountdownEvent,SemaphoreSlim,ManualResetEventSlim.   一:CountdownEvent      这种采用信号状态的同步基元非常适合在动态的fork,join的场景,它采用"信号计数"的方式,就比如这样,一个麻将桌只能容纳4个 人打麻将,如果

单点登录多用户触发同步机制

问题描述 单点登录多用户触发同步机制 多用户同步指每次什么时间点来触发用户同步机制? 注:有些用户是长时间不会登陆的 解决方案 keep-alive心跳机制,服务器推,等等.

Java同步机制浅谈――synchronized对代码作何影响?

Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题.到底如何?――还得对synchronized关键字的作用进行深入了解才可定论.总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.如果再细的分类,synchronized可作用于instance变量.object reference(对象引用).static函数和class literals(类名

探索Java同步机制

本文将从两个方面进行阐述: 使用 C++ 语言来描述 Monitor Object 设计模式.Java 对于这样一个典型的 模式做了很好的语言层面的封装,因此对于 Java 的开发者来说,很多关于该模 式本身的东西被屏蔽掉了.本文试图使用 Native C++ 语言,帮助读者从本质上 对 Monitor object 设计模式有一个更全面的认识. 结合 C++ 版本的 Monitor Object 设计模式,引领读者对于 Java 同步机制 有一个更深刻的认识,帮助读者正确有效地使用 Java