定义在头文件linux/spinlock.h或linux/rwlock.h中;
自旋锁并不关心其锁定的临界区究竟会进行怎么样的操作,不管是读还是写,都一视同仁,即便是多个执行单元同时并发地读取临界区资源,也会被锁住;而事实上,对共享资源的访问,多个执行单元同时读取临界资源,是不会有问题的;读写自旋锁可以允许读操作的并发;
读写自旋锁是从自旋锁衍生过来的;它是一种比自旋锁粒度更小的锁机制,它保留了自旋锁中"自旋"的概念,但是在写操作方面,允许最多只有一个写执行单元操作,而在读操作方面,可以允许同时有多个读执行单元并发操作;当然,读操作和写操作也不能同时进行;
1).定义并初始化读写自旋锁:
rwlock_t my_rwlock1 = RW_LOCK_UNLOCKED; //静态初始化
rwlock_t my_rwlock2;
rwlock_init(&my_rwlock2); //动态初始化
2).读锁定:
void read_lock(rwlock_t* lock);
void read_lock_irqsave(rwlock_t* lock, unsigned long flags);
void read_lock_irq(rwlock_t* lock);
void read_lock_bh(rwlock_t* lock);
3).读解锁:
void read_unlock(rwlock_t* lock);
void read_unlock_irqrestore(rwlock_t* lock, unsigned long flags);
void read_unlock_irq(rwlock_t* lock);
void read_unlock_bh(rwlock_t* lock);
在对共享资源进行读取之前,应该先调用读锁定函数锁定共享资源,完成之后再调用读解锁函数释放共享资源;
4).写锁定:
void write_lock(rwlock_t* lock);
void write_lock_irqsave(rwlock_t* lock, unsigned long flags);
void write_lock_irq(rwlock_t* lock);
void write_lock_bh(rwlock_t* lock);
void write_trylock(rwlock_t* lock);
5).写解锁:
void write_unlock(rwlock_t* lock);
void write_unlock_irqrestore(rwlock_t* lock);
void write_unlock_irq(rwlock_t* lock);
void write_unlock_bh(rwlock_t* lock);
在对共享资源进行写操作之前,应该先调用写锁定函数锁定共享资源,完成之后再调用写解锁函数释放共享资源;与spin_trylock()一样,write_trylock()也只是尝试获得写自旋锁,不管是否成功,都会立即返回;
读写自旋锁使用套路:
rwlock_t lock;      //定义读写自旋锁
rwlock_init(&lock); //初始化读写自旋锁

read_lock(&lock);   //读时加锁
......
//临界区操作
......
read_unlock(&lock); //读后解锁;

write_lock_irqsave(&lock, flags);    //写时加锁
......
//临界区操作
......
write_lock_irqrestore(&lock, flags); //写后解锁;
例子:
#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/spinlock.h> 或
#include <linux/rwlock.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:定义读写自旋锁
rwlock_t my_rw_spin_lock;

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

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

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

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

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:初始化读写自旋锁
 rwlock_init(&my_rw_spin_lock);
 printk("init spin lock 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 =

内核并发控制---读写自旋锁 (来自网易)相关推荐

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

    定义在头文件linux/rwsem.h或linux/rwsem-spinlock.h中 读写信号量与信号量之间的关系,类似于读写自旋锁与自旋锁之间的关系;读写信号量可能会引起进程阻塞,但是它允许N个读 ...

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

    定义在头文件linux/mutex.h中; 互斥体(mutex)是Linux系统提供的另外一种互斥机制;在Linux内核中是真实存在的; 1).定义互斥体 struct mutex my_mutex; ...

  3. 内核并发控制---完成量 (来自网易)

    定义在头文件linux/completion.h中; 完成量(completion)是Linux系统提供的一种比信号量更好的同步机制,是对信号量的一种补充;它用于一个执行单元等待另一个执行单元完成某事 ...

  4. liunx内核中的互斥自旋锁和读写自旋锁的实现详解

    今天把这两个锁的内核实现源码重新捋了一遍,基于liunx2,6.0,直接粘注释版: 核心文件,x86下实现的spinlock #ifndef __ASM_SPINLOCK_H #define __AS ...

  5. 读写自旋锁详解,第 2 部分(来自IBM)

    读者优先的读写自旋锁 我们先不考虑性能,搞出一个可用的实现再说.首先,用一个整型变量 status 来记录当前状态:另一个整型变量 nr_readers 来记录同时持有锁的读者数量,只有当 nr_re ...

  6. 读写自旋锁,第1部分(来自IBM)

    读写自旋锁简介 什么是读写自旋锁 由于互斥的特点,使用自旋锁的代码毫无线程并发性可言,多处理器系统的性能受到限制.通过观察线程在临界区的访问行为,我们发现有些线程只是简单地读取信息,并不修改任何东西, ...

  7. 读写自旋锁详解,第 3 部分(来自IBM)

    基于简单共享变量的读写自旋锁的不足 本系列文章的第 2 部分中给出的实现都基于简单共享变量,简洁实用,但在大规模多核.NUMA 系统上可扩展性较差.我们说某个读写自旋锁的实现是可扩展的,通俗地讲是指在 ...

  8. 内核同步机制——自旋锁

    由于关键代码区可以跨越了多个函数或数据结构,需要有更通用的同步方法:锁. 内核中最常见的一种锁就是自旋锁.相同的锁可用于多处. 自旋锁可用在不可睡眠的场景,如中断处理函数.自旋锁是一种互斥设备,只有两 ...

  9. 读写自旋锁详解:TODO

    林 昊翔 2011 年 7 月 21 日发布 Table of Contents 读写自旋锁简介 什么是读写自旋锁 读写自旋锁的属性 以自动机的观点看读写自旋锁 读写自旋锁的实现细节 读写自旋锁的接口 ...

最新文章

  1. hdu 4012(bfs+位压缩)
  2. jsp页面提示“Multiple annotations found at this line: - The superclass javax.servlet.http.HttpServlet w
  3. Spark _20 _Spark_Shuffle调优
  4. USACO Training Section 1.3混合牛奶 Mixing Milk
  5. 三行代码生成验证码并转换成base64
  6. lsof 命令实用用法介绍
  7. poll函数_如何理解IO多路复用的三种机制Select,Poll,Epoll?
  8. python新手入门代码-新手必看:手把手教你入门 Python
  9. 嵌入式基础面八股文——并发,同步,异步,互斥,阻塞,非阻塞的理解(2)
  10. 20190905每日一句
  11. linux通过usb链接网络,Nokia N9 通过USB连接使用PC(Linux)主机的网络
  12. 51单片机点亮数码管,单片机学习的好的办法,单片机例子大全,单片机教程
  13. Alfred神器使用手册
  14. 性能监控——cpu使用率过高,该怎么分析?
  15. 【简单详细】为Unity游戏制作开场动画video,新手必看
  16. CAS实现的单点登录系统
  17. 无法解析的外部符号 Direct3DCreate9@4
  18. C++中的名字空间和作用域
  19. java 基础面试练习题(易错题)
  20. 团队八种角色缺乏_缺乏信任会对团队造成什么影响

热门文章

  1. matlab第六章课后答案,matlab作业第6章
  2. python中列表生成式strip_python之列表生成式
  3. maven导出Java方法_eclipse导出maven工程的可执行jar包
  4. java跟c 的区别_【c++跟java的区别】java跟c语言的区别
  5. python中文人名识别(使用hanlp,LTP,LAC)
  6. selenium隐式等待
  7. PySide: 信号、槽
  8. 人脸识别dlib库 记录
  9. c语言程序与设计第三版-苏小红--第一轮学习笔记、难点整理
  10. Java串口通信详解(转)