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

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

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

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

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

  1. void wait_for_completion(struct completion *comp);

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

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

  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函数中,大致如下:

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

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

  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信号注销恢复线程,它也需要在线程真正退出后才能释放线程所占用的内存。因此,其逻辑是:

  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的逻辑是:

  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;

 
 

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

  1. 【av68676164(p31-p32)】Windows和Linux同步机制

    4.6.1 Windows同步机制 临界区(CRITICAL_SECTION) 在进程内使用,保证仅一个线程可以申请到该对象 临界区内是临界资源的访问 相关的API函数 初始化临界区 WINBASEA ...

  2. Linux同步机制(二) - 条件变量,信号量,文件锁,栅栏

    1 条件变量 条件变量是一种同步机制,允许线程挂起,直到共享数据上的某些条件得到满足. 1.1 相关函数 #include <pthread.h>  pthread_cond_t cond ...

  3. Linux同步机制(一) - 线程锁

    1 互斥锁 在线程实际运行过程中,我们经常需要多个线程保持同步. 这时可以用互斥锁来完成任务.互斥锁的使用过程中,主要有 pthread_mutex_init pthread_mutex_destor ...

  4. linux同步机制

    很早之前就接触过同步这个概念了,但是一直都很模糊,没有深入地学习了解过,近期有时间了,就花时间研习了一下<linux内核标准教程>和<深入linux设备驱动程序内核机制>这两本 ...

  5. linux同步机制2

    一.并发控制(1)自旋锁得不到资源,会原地打转,直到获得资源为止定义自旋锁 spinlock_t spin;初始化自旋锁 spin_lock_init(lock);获得自旋锁spin_lock(loc ...

  6. Linux同步机制 - 多线程开发总结

    1 对于CPU开销大的场景,能利用多核,就尽量利用多核(常常自以为某需求的运算量不大,且CPU足够快,就偷懒写个单线程,结果效率很低) 2 使用多线程的时候,默认是加锁的.在加锁保证业务正常的条件下, ...

  7. Linux同步机制 - 基本概念(死锁,活锁,饿死,优先级反转,护航现象)

    死锁(deadlock) 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进 ...

  8. Linux内核同步机制

    http://blog.csdn.net/bullbat/article/details/7376424 Linux内核同步控制方法有很多,信号量.锁.原子量.RCU等等,不同的实现方法应用于不同的环 ...

  9. Linux 内核同步机制

        本文将就自己对内核同步机制的一些简要理解,做出一份自己的总结文档.     Linux内部,为了提供对共享资源的互斥访问,提供了一系列的方法,下面简要的一一介绍. Technorati 标签: ...

随机推荐

  1. android的m、mm、mmm编译命令的使用

    android的m.mm.mmm编译命令的使用   android源码目录下的build/envsetup.sh文件,描述编译的命令 - m:       Makes from the top of ...

  2. 关于jsp页面 title中文乱码问题的解决方法

    我知道了 我jsp饮用了html 是我2个页面都写了Title 然后冲突了 就乱码了 分享给大家

  3. 自定义View常处理的回调函数

    自定义View常处理的回调函数 onFinishInflate() 当View中所有的子控件均被映射成xml后触发 onMeasure(int, int) 确定所有子元素的大小 onLayout(bo ...

  4. map遍历的四种方式

    原文 http://blog.csdn.net/dayanxuqun/article/details/26348277 以下是map遍历的四种方式: // 一.推荐只用value的时候用,都懂的... ...

  5. Intellij Idea搭建java web项目(问题总结)

    这两天突发奇想下载了Intellij Idea,准备体验下这个传说中很强大IDE.工具下载就不多说了,网上一搜便知,博主是直接从Intellij官网下载的最新完整版,可惜的是只能使用30天,不过也差不 ...

  6. Linux服务器软件安装备忘

    1.Centos安装Mysql --安装 yum install mysql-server 卸载 yum -e mysql-server --设置为开机启动 chkconfig mysqld on - ...

  7. android4.0 的图库Gallery2代码分析(二)

    最近迫于生存压力,不得不给人兼职打工.故在博文中加了个求点击的链接.麻烦有时间的博友们帮我点击一下.没时间的不用勉强啊.不过请放心,我是做技术的,肯定链接没病毒,就是我打工的淘宝店铺.嘻嘻.http: ...

  8. Java IO整理

    参考博客:http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html Java   IO体系结构 1.要弄清楚其体系结构,先明白 ...

  9. Sping--IOC概念

    1. 新建项目, 引入spring包(sping, common-annotation, common-logging包), 还有junit包. user.java: package com.bjsx ...

  10. 一、Hbase的安装

    一.Hbase配置 这个是我从网上找的一个版本,网上说配置成功. 先决条件: (1)hadoop的版本与hbase的版本要对应,主要是hadoop目录下的hadoop-core-1.0.4.jar的版 ...