读写信号量
读写信号量是对互斥信号量的改进,允许多个读者同时进入临界区,读者和写者互斥,写者和写者互斥,适合在以读为主的情况使用。
读写信号量的定义如下:
include/linux/rwsem.h
struct rw_semaphore {
atomic_long_t count;
struct list_head wait_list;
raw_spinlock_t wait_lock;
struct task_struct *owner;
…
};
初始化静态读写信号量的方法如下:
DECLARE_RWSEM(name);
在运行时动态初始化读写信号量的方法如下:
init_rwsem(sem);
申请读锁的函数如下。
(1)void down_read(struct rw_semaphore *sem);
申请读锁,如果写者占有写锁或者正在等待写锁,那么进程深度睡眠。
(2)int down_read_trylock(struct rw_semaphore *sem);
尝试申请读锁,不会等待。如果申请成功,返回 1;否则返回 0。
释放读锁的函数如下:
void up_read(struct rw_semaphore *sem);
申请写锁的函数如下。
(1)void down_write(struct rw_semaphore *sem);
申请写锁,如果写者占有写锁或者读者占有读锁,那么进程深度睡眠。
(2)int down_write_killable(struct rw_semaphore *sem);
申请写锁,如果写者占有写锁或者读者占有读锁,那么进程中度睡眠。
(3)int down_write_trylock(struct rw_semaphore *sem);
尝试申请写锁,不会等待。如果申请成功,返回 1;否则返回 0。
占有写锁以后,可以把写锁降级为读锁,函数如下:
void downgrade_write(struct rw_semaphore *sem);
释放写锁的函数如下:
void up_write(struct rw_semaphore *sem);
#include <linux/rwsem.h>
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init down_read_init(void);
static void __exit down_read_exit(void);
#define EXEC_DOWN_WRITE 0
#define EXEC_DOWN_READ 1
struct rw_semaphore rwsem ;
static int sem = EXEC_DOWN_READ;
module_param(sem, int, 0644);
MODULE_PARM_DESC(sem, "sem");
int __init down_read_init(void)
{
init_rwsem( &rwsem ); //读写信号量初始化
printk("after init_rwsem, count: %ld\n", rwsem.count);
if( EXEC_DOWN_WRITE == sem )
down_write( &rwsem ); //写者获取读写信号量
down_read( &rwsem ); //读者获取读写信号量
printk("first down_read, count: %ld\n", rwsem.count);
down_read( &rwsem );
printk("second down_read, count: %ld\n", rwsem.count);
while( rwsem.count.counter != 0 )
{
up_read( &rwsem ); //读者释放读写信号量
}
return 0;
}
void __exit down_read_exit(void)
{
printk("exit! \n");
}
module_init(down_read_init);
module_exit(down_read_exit);
~
sudo insmod rwsem.ko sem=0
sudo insmod rwsem.ko sem=1