linux驱动(第八课,互斥,同步,并发控制)

驱动虽然是运行在内核空间的,但是驱动是运行在进程上下文中的,
当系统中有多个进程并发的请求驱动的服务时,就会导致竞态,所以驱动必须解决的问题就是对共享资源的访问。
并发访问会导致竞态。

当内核的多条执行路径同时访问同一个共享资源时,就会造成竞态。
例如中断ISR的执行,或者多核CPU的不同CPU核的并行执行。
常见的共享资源有,全局变量,共享内存,等等。

解决竞态的方法是,保证对共享资源的互斥访问。
访问共享资源的代码段,成为临界代码段。(critical section)
linux中提供了多种实现互斥的方法,包括
中断屏蔽,原子操作,自旋锁,信号量,互斥体。

在驱动开发中,推荐使用的是spinlock和mutex。
mutex的实现依赖于spinlock,即,spinlock是更底层的互斥手段。
使用mutex和spinlock有如下基本原则:
1)当锁不可得时,mutex的开销是process context的切换时间,而spinlock的开销是spin,所以,如果临界代码段很小,推荐使用spinlock,节省开销。
2) mutex保护的临界代码段,可以包含引起阻塞的代码,但是spinlock绝对禁止保护可能阻塞的代码。阻塞意味着进程切换,如果进程被切换,而另一个进程又试图获取spinlock,死锁就会发生。
3)mutex存在与process context,所以,如果需要在ISR或者SISR中使用,那么只能使用spinlock,或者使用mutex_trylock()进行访问,避免阻塞。

来看看具体的应用。
作为内核通信的一种机制,互斥也是一种event driven communication。
所以,无论是spinlock还是mutex,都对应于一个对象实体。
利用kernel提供的服务函数,对spinlock或者mutex的成员进行修改,并对进程进行相应的处理。

mutex会引起进程调度,
当mutex_lock内核服务被请求时,内核会检查mutex的数据,并对进程进行调度和阻塞,然后修改mutex的数据。
当mutex_unlock内核服务被请求时,内核会检查mutex的数据,并对关联的阻塞进程进行唤醒,然后修改mutex的数据。
整个过程中,进程都只是和kernel进行通信,kernel负责调度,进程间通过kernel间接实现互斥通信。

spinlock不会引起进程调度,
当spin_lock内核服务被请求时,内核会检查spinlock的数据,如果锁不可得,进程自旋等待下一次测试。如果锁可得,内核会修改spinlock的数据,并返回,执行后续的代码。
当spin_unlock内核服务被请求时,内核会修改spinlock的数据,并返回,执行后续的代码。
来看一个具体的例子。

struct globalmem_dev{
	struct cdev cdev;
	unsigned char mem[SIZE];
	struct mutex mutex;
};

DEV中内嵌一个CDEV,为了实现互斥,DEV中内嵌了一个mutex。
当进程调用DEV的DRIVER时,首先去尝试获得这个mutex,这样就可以防止多个进程并发调用DRIVER,对mem访问发生竞态。

static struct globalmem_dev globalmem;

static int __init globalmem_dev_init()
{
	int ret;
	...
	mutex_init(&globalmem.mutex);
	...
	return ret;
}
module_init(globalmem_dev_init);

在驱动加载函数中,初始化了Mutex.

static ssize_t globalmem_read(struct file* filp, char __user *buf, size_t size, loff_t* ppos)
{
	int ret;
	struct globalmem_dev * devp = filp->private_data;
	...
	mutex_lock(&devp->mutex);
	copy_to_user(buf, dev->mem, count);
	mutex_unlock(&devp->mutex);
	...
	return ret;
}

static ssize_t globalmem_write(struct file* filp, char __user *buf, size_t size, loff_t* ppos)
{
	int ret;
	struct globalmem_dev * devp = filp->private_data;
	...
	mutex_lock(&devp->mutex);
	copy_from_user(dev->mem,buf, count);
	mutex_unlock(&devp->mutex);
	...
	return ret;
}

在FOPS中,对访问公共资源的代码段,进行互斥保护。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值