定义在头文件linux/completion.h中;
完成量(completion)是Linux系统提供的一种比信号量更好的同步机制,是对信号量的一种补充;它用于一个执行单元等待另一个执行单元完成某事;使用完成量等待时,调用进程是以独占睡眠方式进行等待的;不是忙等待;
1).定义完成量:
struct completion my_completion;    //定义完成量my_completion
2).初始化完成量:
init_completion(&my_completion);    //初始化完成量my_completion
DECLARE_COMPLETION(my_completion);  //初始化完成量my_completion的快捷方式
3).等待完成量:
void wait_for_completion(struct completion* comp):
该函数等待一个完成量被唤醒;该函数会阻塞调用进程,如果所等待的完成量没有被唤醒,那就一直阻塞下去,而且不会被信号打断;
int wait_for_completion_interruptible(struct completion* comp):
该函数等待一个完成量被唤醒;但是它可以被外部信号打断;
int wait_for_completion_killable(struct completion* comp):
该函数等待一个完成量被唤醒;但是它可以被kill信号打断;
unsigned long wait_for_completion_timeout(struct completion* comp, unsigned long timeout):
该函数等待一个完成量被唤醒;该函数会阻塞调用进程,如果所等待的完成量没有被唤醒,调用进程也不会一直阻塞下去,而是等待一个指定的超时时间timeout,当超时时间到达时,如果所等待的完成量仍然没有被唤醒,那就返回;超时时间timeout以系统的时钟滴答次数jiffies计算;
bool try_wait_for_completion(struct completion* comp):
该函数尝试等待一个完成量被唤醒;不管所等待的完成量是否被唤醒,该函数都会立即返回;
bool completion_done(struct completion* comp):
该函数用于检查是否有执行单元阻塞在完成量comp上(是否已经完成),返回0,表示有执行单元被完成量comp阻塞;相当于wait_for_completion_timeout()中的timeout=0;
注意:这几个函数都会把进程添加到等待队列中,进程在等待队列中以独占睡眠方式进行等待,直到请求被内核中的某些部分处理;
4).唤醒完成量:
void complete(struct completion* comp):
该函数只唤醒一个正在等待完成量comp的执行单元;
void complete_all(struct completion* comp):
该函数唤醒所有正在等待同一个完成量comp的执行单元;
NORET_TYPE void complete_and_exit(struct completion* comp, long code):
该函数唤醒一个正在等待完成量comp的执行单元,并退出,code为退出码;
注意:在内核处理完请求之后,必须调用这三个函数中的一个,来唤醒其它正在等待的进程;
例子:
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/delay.h>

//这三个头文件与内核线程的使用有关;
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/err.h>

//完成量相关
#include <linux/completion.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("*************");
MODULE_VERSION("2.6.35.000");

static int sleep_time = (1*10*HZ);
static int shared_res = 0;

//STEP1:定义完成量
struct completion my_comp;

//STEP5:实现线程函数
static int thread_process1(void* param)
{
  //int val = 0, ret = 0;

while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

//STEP3:对临界区加锁
    wait_for_completion(&my_comp);
    shared_res++;
    //STEP4:对临界区解锁
    complete(&my_comp);

mdelay(sleep_time);
  }
  return 12;
};

static int thread_process2(void* param)
{
  //int val = 0, ret = 0;

while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

//STEP3:对临界区加锁
    wait_for_completion(&my_comp);
    shared_res++;
    //STEP4:对临界区解锁
    complete(&my_comp);

msleep(sleep_time);
  }
  return 34;
};

static int thread_process3(void* param)
{
  int val = 0;//, ret = 0;

while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

//STEP3:对临界区加锁
    wait_for_completion(&my_comp);
    val = shared_res;
    printk("%s: shared resource = %d;\n%s", __FUNCTION__, val, ((val % 3) ? "" : "\n"));
    //STEP4:对临界区解锁
    complete(&my_comp);

msleep(sleep_time);
  }
  return 56;
};

static int thread_process4(void* param)
{
  int val = 0;//, ret = 0;

while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

//STEP3:对临界区加锁
    wait_for_completion(&my_comp);
    val = shared_res;
    printk("%s: shared resource = %d;\n%s", __FUNCTION__, val, ((val % 3) ? "" : "\n"));
    //STEP4:对临界区解锁
    complete(&my_comp);

msleep(sleep_time);
  }
  return 78;
};

static struct task_struct* my_thread1 = NULL;
static struct task_struct* my_thread2 = NULL;
static struct task_struct* my_thread3 = NULL;
static struct task_struct* my_thread4 = NULL;

static int __init study_init(void)
{
 int err = 0;
 printk("%s\n", __PRETTY_FUNCTION__);

//STEP2:初始化完成量
 init_completion(&my_comp);
 printk("init completion ok\n");
 complete_all(&my_comp);

my_thread1 = kthread_create(thread_process1, NULL, "my_thread1");
 if(IS_ERR(my_thread1))
 {
   err = PTR_ERR(my_thread1);
   my_thread1 = NULL;
   printk(KERN_ERR "unable to start kernel thread1:%d\n", err);
   return err;
 }

my_thread2 = kthread_create(thread_process2, NULL, "my_thread2");
 if(IS_ERR(my_thread2))
 {
   err = PTR_ERR(my_thread2);
   my_thread2 = NULL;
   printk(KERN_ERR "unable to start kernel thread2:%d\n", err);
   return err;
 }

my_thread3 = kthread_create(thread_process3, NULL, "my_thread3");
 if(IS_ERR(my_thread3))
 {
   err = PTR_ERR(my_thread3);
   my_thread3 = NULL;
   printk(KERN_ERR "unable to start kernel thread3:%d\n", err);
   return err;
 }

my_thread4 = kthread_create(thread_process4, NULL, "my_thread4");
 if(IS_ERR(my_thread4))
 {
   err = PTR_ERR(my_thread4);
   my_thread4 = NULL;
   printk(KERN_ERR "unable to start kernel thread4:%d\n", err);
   return err;
 }

wake_up_process(my_thread1);
 wake_up_process(my_thread2);
 wake_up_process(my_thread3);
 wake_up_process(my_thread4);
 printk("%s:all kernel thread start;\n", __FUNCTION__);
 return 0;
}

static void __exit study_exit(void)
{
 int ret = -1;
 printk("%s\n",__PRETTY_FUNCTION__);

//complete_all(&my_comp);
 complete(&my_comp);

if(my_thread1)
 {
   ret = kthread_stop(my_thread1);
   my_thread1 = NULL;
   printk("kernel thread1 stop,exit code is %d;\n",ret);
 }

//complete_all(&my_comp);
 complete(&my_comp);

if(my_thread2)
 {
   ret = kthread_stop(my_thread2);
   my_thread2 = NULL;
   printk("kernel thread2 stop,exit code is %d;\n",ret);
 }

//complete_all(&my_comp);
 complete(&my_comp);

if(my_thread3)
 {
   ret = kthread_stop(my_thread3);
   my_thread3 = NULL;
   printk("kernel thread3 stop,exit code is %d;\n",ret);
 }

//complete_all(&my_comp);
 complete(&my_comp);

if(my_thread4)
 {
   ret = kthread_stop(my_thread4);
   my_thread4 = NULL;
   printk("kernel thread4 stop,exit code is %d;\n",ret);
 }

printk("%s:all kernel thread stop;\n", __FUNCTION__);
}

module_init(study_init);
module_exit(study_exit);

内核并发控制---完成量 (来自网易)相关推荐

  1. 内核并发控制---中断屏蔽 (来自网易)

    定义在头文件linux/irqflags.h中; 在单CPU内部避免竞态的一种方法是在进入临界区之前先屏蔽系统的中断,离开临界区之前再恢复系统中断;CPU一般都应该具有打开中断和关闭中断的功能;这项功 ...

  2. 内核并发控制---信号量 (来自网易)

    定义在头文件linux/semaphore.h中; 信号量(semaphore)是用于保护临界区的一种常用方法,它的使用方式与自旋锁类似;与自旋锁相同,只有得到信号量的进程才能执行临界区的代码;但是, ...

  3. 内核并发控制---原子操作(来自网易)

    定义在头文件asm/atomic.h中; 原子操作指的是在执行过程中不会被别的代码路径所打断的操作; Linux内核提供了一系列的函数来实现内核中的原子操作,这些函数又分为两类,分别针对位变量和整型变 ...

  4. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  5. linux内核同步之信号量、顺序锁、RCU、完成量、关闭中断【转】

    转自:http://blog.csdn.net/goodluckwhh/article/details/9006065 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一信号量 ...

  6. linux 3.10中完成量的使用

    完成量是基于等待队列设计的,所以显然不能在中断上下文使用完成量. struct completion {unsigned int done;wait_queue_head_t wait; }; 我们来 ...

  7. linux中同步例子(完成量completion)

    这是一个公交司机和售票员之间的线程调度,用于理解完成量,完成量是对信号量的一种补充,主要用于多处理器系统上发生的一种微妙竞争 在这里两个线程间同步,只有当售票员把门关了后,司机才能开动车,只有当司机停 ...

  8. Linux驱动 - 多线程之 完成量

    Linux 系统提供了一种比信号量更好的同步机制,即完成量(completion ,它用于一个执行单元等待另一个 执行单元执行完某事. Linux 系统中与 completion 相关的操作主要有以下 ...

  9. 内核并发控制---RCU (来自网易)

    定义在头文件linux/rcupdate.h中; 一.RCU原理 RCU,全名Read-Copy-Update(读-拷贝-更新);对于被RCU所保护的共享资源,读执行单元不需要获得任何锁就可以访问到它 ...

最新文章

  1. (第7篇)灵活易用易维护的hadoop数据仓库工具——Hive
  2. 利用HTML5的devicemotion事件实现手机摇一摇抽奖,年会抽奖
  3. 怎么调整字段长短_木北造型:空气刘海卷发筒怎么用 木北造型告诉您
  4. 详解Windows开机自动运行
  5. Tomcat5.5报错:Apache Portable Runtime was not found
  6. 第二章 数据的表示和运算 2.1.4 奇偶校验 [计算机组成原理笔记]
  7. 《spring-boot学习》-02-hello world
  8. 如何使用IEDA连接数据库
  9. [转载] Python中numpy.clip();numpy.fabs()的用法;以及math.pow()的说明
  10. LordPe dump进程内存实现
  11. Qt制作局域网即时通讯软件
  12. python弧度角度转换程序_python 弧度与角度互转实例
  13. 罗斯柴尔德家族与人类的四次战争
  14. DIY成本35的自制蓝牙音响
  15. UI文案设计技巧,视觉与内容兼具不再是梦
  16. 比较IC卡、ID卡、M1卡、CPU卡它们之间有什么区别?
  17. vue文件命名规范和文件夹命名规范
  18. 混淆问题(常见问题汇总)
  19. 桃源恋歌歌词-罗马音
  20. Codeforces Round #701 (Div. 2) 总结

热门文章

  1. 2021赣一中高考成绩查询,赣州中学2021年高一招生问答
  2. linux执行使分区生效的命令,Linux硬盘分区生效命令partprobe
  3. django新建utils文件夹与导入方法
  4. sklearn网格搜索GridSearchCV得到各个评价指标的均值与方差
  5. tshark 解析pcap中带TLS协议的数据包
  6. java http zip参数,如何从Web API 2 HttpGet发送zip文件
  7. java ldap 实例_JAVA_基本LDAP操作实例
  8. c++去除图片上的文字_图片文字修改去除方法
  9. 洛谷P2134 百日旅行
  10. 基于EasyDSS流媒体服务器实现的直播流管理与鉴权的后台方案