定义在头文件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 =