zoukankan      html  css  js  c++  java
  • 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;

     
     
  • 相关阅读:
    法语助手2010破解
    一个很简单的例子,从汇编层次理解函数调用
    ubuntu11.10配置IPV6
    linux创建 / 删除用户及用户管理
    设置gdb反汇编语法为intel
    ubuntu server 10.04 LTS(64位)装不了花生壳的解决方法
    实现windows和linux互传文件
    在ubuntu11.10中安装chrome浏览器
    poj 1755 Triathlon 半平面交判断不等式是否有解
    poj 1474 Video Surveillance 半平面交
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/6288874.html
Copyright © 2011-2022 走看看