linux驱动程序中的并发控制-6(读写信号量)-48
Posted 杨斌并
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux驱动程序中的并发控制-6(读写信号量)-48相关的知识,希望对你有一定的参考价值。
读写信号量
- 读写信号量和信号量的关系与读写自旋锁和自旋锁的关系类似。
- 读信号量和写信号量是互斥的,但允许N个读执行单元同时访问共享资源(同时获取读信号量),而最多只允许有一个写单元获取写信号量。
- 读写信号量相对于信号量更宽松,对于读多写少的情况会明显提高程序的执
行效率。
读写信号量的使用
- 定义和初始化读写信号量
- rw_semaphore 结构体(#include <linux/rwsem.h>)
struct rw_semaphore
long count;
struct list_head wait_list;
raw_spinlock_t wait_lock;
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
struct optimistic_spin_queue osq; /* spinner MCS lock */
/*
* Write owner. Used as a speculative check to see
* if the owner is running on the cpu.
*/
struct task_struct *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
;
- 定义和初始化
struct rw_semaphore rw_sem;
init_rwsem(&rw_sem);
- 获取信号量
extern void down_write(struct rw_semaphore *sem);
extern int down_write_trylock(struct rw_semaphore *sem);
- down_read函数用于获取读信号量,如果无法获取读信号量则会休眠。
- down_read_trylock 函数不管是否能获取读信号量都会立即返回。如果成功获取读信号量则返回1,否则返回0。
- 获取写信号量
extern void up_write(struct rw_semaphore *sem);
extern void downgrade_write(struct rw_semaphore *sem);
- down_write 函数用于获取写信号量,如果无法获取写信号量则会休眠。
- down_write_trylock 函数不管是否能获取写信号量都会立即返回。如果成功获取写信号量则返回1,否则返回0。
实例
- rw_semaphore_test.c
//
// semaphore_rw_test.c
// seqlock_demo
//
// Created by lianfei on 2021/7/13.
//
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
struct rw_semaphore rw_sem;
#define DEVICE_RCU_NAME "rw_semaphore"
static ssize_t demo_read(struct file *file, char __user * buf, size_t count, loff_t *ppos)
struct timeval tv;
do_gettimeofday(&tv);
printk("rw_semaphore read: start %ld\\n", tv.tv_sec);
//获取读型号量
down_read(&rw_sem);
printk("rw_semaphore read: end %ld\\n", tv.tv_sec);
mdelay(10000);
up_read(&rw_sem);
return 0;
static ssize_t demo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
struct timeval tv;
do_gettimeofday(&tv);
printk("write: start %ld \\n", tv.tv_sec);
down_write(&rw_sem);
do_gettimeofday(&tv);
printk("write: end %ld \\n", tv.tv_sec);
up_write(&rw_sem);
return count;
static int demo_release(struct inode *node, struct file *file)
return 0;
static int demo_open(struct inode *node, struct file *file)
return 0;
static struct file_operations dev_fops=
.owner = THIS_MODULE,
.open = demo_open,
.release = demo_release,
.read = demo_read,
.write = demo_write
;
static struct miscdevice misc=
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_RCU_NAME,
.fops = &dev_fops
;
static int demo_init(void)
int ret=misc_register(&misc);
if(ret < 0 )
printk("atomic_init is error\\n");
return -1;
printk("demo_init_success\\n");
init_rwsem(&rw_sem);
return ret;
static void demo_exit(void)
printk("ademo_exit_success\\n");
misc_deregister(&misc);
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("binbing.Yang");
- 测试脚本
- rw_semaphore_test.sh
#!/system/bin/sh
cat /dev/rw_semaphore &
cat /dev/rw_semaphore &
cat /dev/rw_semaphore &
sleep 5
echo abcd > /dev/rw_semaphore
通过对设备文件的读写,演示如何使用读写信号量保护临界区的代码。在读设备文件时调用的demo_ read函数中使用了down_ read 函数获取读信号量,并且使用mdelay函数延迟5秒.来模拟读临界区代码的执行过程。在向设备文件写入数据时调用的demowrite函数中使用了down_ write 函数获取写信号量。从这一点可以看 出,多次调用demo read函数并不会被阻塞,但调用demo_read函数后再调用demo_write函数就会被阻塞(由于读信号量未被释放)。
以上是关于linux驱动程序中的并发控制-6(读写信号量)-48的主要内容,如果未能解决你的问题,请参考以下文章