linux驱动22:自旋锁spinlock

自旋锁:

和信号量不同的是自旋锁可在不能休眠的代码中使用,如中断处理例程。在正确使用时,自旋锁通常比信号量具有更高的性能。

如果锁可用,则锁定位被设置,代码继续进入临界区;相反则代码进入忙循环并重复检查锁,直到该锁可用。

所有自旋锁在本质上是不可中断的,一旦调用了spin_lock,在获得锁之前一直处于自旋状态。

自旋锁的实现由于linux所支持的架构不同而不同。

自旋锁的核心规则是:任何拥有自旋锁的代码必须是原子的。自旋锁不能休眠。

自旋锁必须在可能的最短时间内拥有。

头文件:<linux/spinlock.h>

初始化:

        静态:spinlock_t lock;

        动态:void spin_lock_init(spinlock_t *lock);

获取锁:

void spin_lock(spinlock_t *lock);

void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);

获得自旋锁之前禁止中断,先前的中断状态保存在flags中。

void spin_lock_irq(spinlock_t *lock);

确保释放自旋锁时应该启用中断时调用。

void spin_lock_bh(spinlock_t *lock);

获得锁之前禁止软件中断。

释放锁:

void spin_unlock(spinlock_t *lock);

void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);

void spin_unlock_irq(spinlock_t *lock);

void spin_unlock_bh(spinlock_t *lock);

非阻塞自旋锁:

int spin_trylock(spinlock_t *lock);

int spin_trylock_bh(spinlock_t *lock);

获得自旋锁返回非零值,否则返回零。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/spinlock.h>

static int major = 277;
static int minor = 0;
static dev_t helloNum;
static struct class *helloClass = NULL;
static struct device *helloDev = NULL;
static spinlock_t lock;
int busyFlag = 0;

int hello_open(struct inode *pinode, struct file *pfile)
{
	printk("hello_open, minor:%d, major:%d\n", iminor(pinode), imajor(pinode));
	spin_lock(&lock);
	if (1 == busyFlag)
	{
		spin_unlock(&lock);
		return -EBUSY;
	}
	busyFlag = 1;
	spin_unlock(&lock);
	return 0;
}

int hello_release(struct inode *pinode, struct file *pfile)
{
	printk("hello_release, minor:%d, major:%d\n", iminor(pinode), imajor(pinode));
	busyFlag = 0;
	return 0;
}

static struct file_operations hello_ops = {
	.open = hello_open,
	.release = hello_release,
};

static int hello_init(void)
{
	int ret = 0;
	printk("hello_init\n");

	ret = register_chrdev( major, "hello", &hello_ops);
	if(ret < 0)
	{
		printk("register_chrdev failed.\n");
		return ret;
	}

	helloClass = class_create(THIS_MODULE, "hellocls");
	if (IS_ERR(helloClass)) 
	{
		printk("class_create failed.\n");
		ret = PTR_ERR(helloClass);
		goto error_exit1;
	}

	helloNum = MKDEV(major,minor);
	printk("major:%d, minor:%d\n", MAJOR(helloNum), MINOR(helloNum));

	helloDev = device_create(helloClass, NULL, helloNum, NULL, "hello0");
	if (IS_ERR(helloDev)) 
	{
		printk("device_create failed.\n");
		ret = PTR_ERR(helloDev);
		goto error_exit2;
	}
	
	return 0;

error_exit2:
	class_destroy(helloClass);

error_exit1:
	unregister_chrdev(major,"hello");

	return ret;
}

static void hello_exit(void)
{
	printk("hello_exit\n");
	device_destroy(helloClass, helloNum);
	class_destroy(helloClass);
	unregister_chrdev(major,"hello");
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

读取者/写入者自旋锁(了解):

运行任意数量的读取者进入临界区,但写入者必须互斥访问。

rwlock和rwsem类似。

头文件:<linux/spinlock.h>

初始化:

rwlock_init(rwlock_t *lock);

读取者:

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

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

注:没有read_trylock函数。

写入者:

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

int write_trylock(rwlock_t *lock);

void write_unlock(rwlock_t *lock);

void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);

void write_unlock_irq(rwlock_t *lock);

void write_unlock_bh(rwlock_t *lock);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值