定义在头文件linux/rwsem.h或linux/rwsem-spinlock.h中
读写信号量与信号量之间的关系,类似于读写自旋锁与自旋锁之间的关系;读写信号量可能会引起进程阻塞,但是它允许N个读执行单元同时访问共享资源,而最多只允许有一个写执行单元访问共享资源;因此,读写信号量是一种相对放宽条件的、粒度稍大于信号量的互斥机制;
备注:信号量不允许任何操作之间有并发,即:读操作与读操作之间、读操作与写操作之间、写操作与写操作之间,都不允许并发;而读写信号量则只允许读操作与读操作之间可以并发,但不允许读操作与写操作之间的并发,也不允许写操作与写操作之间的并发;
1).定义并初始化读写信号量:
struct rw_semaphore rw_sem;                         //定义读写信号量
void init_rwsem(struct rw_semaphore* rw_sem);       //初始化读写信号量
2).获取和释放读信号量:
void down_read(struct rw_semaphore* rw_sem);        //获取读信号量
int down_read_trylock(struct rw_semaphore* rw_sem); //尝试获取读信号量
void up_read(struct rw_semaphore* rw_sem);          //释放读信号量
3).获取和释放写信号量:
void down_write(struct rw_semaphore* rw_sem);       //获取写信号量
int down_write_trylock(struct rw_semaphore* rw_sem);//尝试获取写信号量
void up_write(struct rw_semaphore* rw_sem);         //释放写信号量
4).读写信号量的使用模式:
rw_semaphore sem;   //定义读写信号量
init_rwsem(&sem);   //初始化读写信号量

down_read(&sem);    //读时获取信号量
......              //临界区代码
up_read(&sem);      //读时释放信号量

down_write(&sem);   //写时获取信号量
......              //临界区代码
up_write(&sem);     //写时释放信号量
5).读写信号量降级:
void downgrade_write(struct rw_semaphore* sem);
该函数用于把写者降级为读者,有时,这是必要的.因为写者是互斥的、排它的,因此在写者保护读写信号量期间,任何读者或写者都将无法访问该信号量所保护的共享资源,对于那些当前条件下不需要写操作的访问者,降级为写者,将使得等待访问的读者能够立即访问,从而增加了并发性,提高了效率;
例子:
#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/rwsem.h>
#include <linux/rwsem-spinlock.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 rw_semaphore my_rw_sem;

//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:对临界区加锁
    down_write(&my_rw_sem);
    shared_res++;
    //STEP4:对临界区解锁
    up_write(&my_rw_sem);

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:对临界区加锁
    down_write(&my_rw_sem);
    shared_res++;
    //STEP4:对临界区解锁
    up_write(&my_rw_sem);

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:对临界区加锁
    down_read(&my_rw_sem);
    val = shared_res;
    printk("%s: shared resource = %d;\n%s", __FUNCTION__, val, ((val % 3) ? "" : "\n"));
    //STEP4:对临界区解锁
    up_read(&my_rw_sem);

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:对临界区加锁
    down_read(&my_rw_sem);
    val = shared_res;
    printk("%s: shared resource = %d;\n%s", __FUNCTION__, val, ((val % 3) ? "" : "\n"));
    //STEP4:对临界区解锁
    up_read(&my_rw_sem);

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_rwsem(&my_rw_sem);
 printk("init rw semaphore ok\n");

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__);

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

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

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

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. 内核并发控制---原子操作(来自网易)

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

  3. 内核并发控制---读写自旋锁 (来自网易)

    定义在头文件linux/spinlock.h或linux/rwlock.h中; 自旋锁并不关心其锁定的临界区究竟会进行怎么样的操作,不管是读还是写,都一视同仁,即便是多个执行单元同时并发地读取临界区资 ...

  4. Linux内核中的同步原语:自旋锁,信号量,互斥锁,读写信号量,顺序锁

    Linux内核中的同步原语 自旋锁,信号量,互斥锁,读写信号量,顺序锁 rtoax 2021年3月 在英文原文基础上,针对中文译文增加5.10.13内核源码相关内容. 1. Linux 内核中的同步原 ...

  5. Linux内核信号量:二值信号量/互斥信号量,计数信号量,读写信号量

    <semaphore信号量:一个简单的示例程序>用户态程序 目录 概念 应用场景 使用方法 内核信号量的构成 信号量的API 初始化 PV操作 获取信号量(P) 释放内核信号量(V) 补充 ...

  6. linux 信号量锁 内核,Linux内核中锁机制之信号量、读写信号量

    在上一篇博文中笔者分析了关于内存屏障.读写自旋锁以及顺序锁的相关内容,本篇博文将着重讨论有关信号量.读写信号量的内容. 六.信号量 关于信号量的内容,实际上它是与自旋锁类似的概念,只有得到信号量的进程 ...

  7. 内核同步机制-读写信号量(rw_semaphore)

    四.读写信号量(rw_semaphore) 读/写信号量适于在读多写少的情况下使用.如果一个任务需要读和写操作时,它将被看作写者,在不需要写操作的情况下可降级为读者.任意多个读者可同时拥有一个读/写信 ...

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

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

  9. 原子操作、信号量、读写信号量和自旋锁

    本系列文章分两部分,第一部分详细地介绍了 Linux 内核中的同步机制:原子操作.信号量.读写信号量和自旋锁的API,使用要求以及一些典型示例.第二部分将详细介绍在Linux内核中的另外一些同步机制, ...

最新文章

  1. Ubuntu 18.04 固件的烧录方法
  2. NOIP2017 列队
  3. 像写SQL一样编写Java数据应用-TinySqlDsl
  4. Python入门100题 | 第066题
  5. 【转】SAP S4 OP/Cloud 10个区别
  6. 【Python】用 Highcharts 绘制饼图,也很强大
  7. 从0搭建在线聊天室,只需4步!
  8. ACL 2019 | 面向远程监督关系抽取的模式诊断技术
  9. 7.IDA-创建结构体
  10. jdk1.8_googleV3免费下载(API中文文档)
  11. 【渝粤教育】国家开放大学2018年秋季 1126t社会医学 参考试题
  12. mysql空间是什么格式_MySQL数据类型 - 空间数据类型 (6)
  13. mysql约束类型 A P_sql数据类型与约束总结
  14. 《Scikit-Learn与TensorFlow机器学习实用指南》第15章 自编码器
  15. Android NDK开发,使用ndk-build编译,写的太详细了
  16. ps+背景缩放+内容缩放
  17. NetFlow Analyzer无线网络管理
  18. 微信邮箱是什么?微信如何绑定邮箱收发邮件?
  19. cisco路由器基本实验之四 动态路由之IGRP协议的配置(Boson NetSim)
  20. c语言处理nc程序,NC程序的语言问题

热门文章

  1. html align 属性,align-content
  2. 解决xgboost报错XGBoostError: XGBoost Library (libxgboost.dylib) could not be loaded
  3. sklearn自定义评价函数
  4. ubuntu18.04 安装(指定版本/最新版)docker与docker compose
  5. 地面波天线怎样能多收台_GPS天线的分类介绍及应用
  6. c语言指针填空题目,C语言指针题目实战
  7. centos7下的elasticsearch-6.2.4安装
  8. Python Web笔记之高性能网络编程
  9. C#WinForm 窗体单例模式 反射单例
  10. 关于 iOS 证书,你必须了解的知识