- 1、本文档共22页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
linux并发和竞争.ppt
并发和竞态 并发和竞态 并发指的是多个执行单元同时,并行被执行。 并发的执行单元对共享资源(硬件资源和软件上的全局变量,静态变量等)的访问则很容易导致竞态。 并发和竞态 对于globalmem设备,假设一个执行单元A对其写入3000个字符’a’,而另一个执行单元B对其写入4000个’b’,第三个执行单元C读取globalmem的所有字符,如果A B 的写操作按照下图进行,执行单元C的读操作不会有问题。 并发和竞态 如果执行单元A B的写操作如下所示,而执行单元C则会读出3000个’b’ 并发和竞态 解决竞态问题的途径是保证对共享资源的互斥访问,所谓互斥访问是指一个执行单元在访问共享资源的时候,其它的执行单元被禁止访问。 访问共享资源的代码区域叫做“临界区”,临界区需要以某种互斥机制加以保护:中断屏蔽,信号量,自旋锁等。 中断屏蔽 避免竞态的一种简单方法是进入临界区之前屏蔽系统的中断,CPU一般都具有屏蔽中断和打开中断的功能,这项功能可以保证正在执行的内核执行路径不被中断处理程序所抢占,防止某些竞态条件的发生,具体而言,中断屏蔽将使得中断与进程之间的并发不再发生,而且,由于linux内核的进程调度等操作都依赖于中断来实现,内核抢占进程之间的并发也就得以避免了。 中断屏蔽的使用方法: local_irq_disable();//屏蔽中断 ………… /*临界区*/ local_irq_enable();//开中断 中断屏蔽 local_irq_save(flags): 除了进行禁止中断的操作以外,还保存目前CPU的中断信息, local_irq_restore(flags)进行的是与loca_irq_save(flags)相反的操作, 自旋锁 自旋锁是一种对临界资源进行互斥访问的典型手段。自旋锁是一种原子操作,其工作原理是测试并设置某个内存变量,通过把该变量标记为不同的状态,从而控制竞态的发生。 自旋锁 自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁,那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的内核任务便能立刻得到它并且继续进行。 spin_lock(mr_lock); //加锁 //临界区 spin_unlock(mr_lock); //解锁 自旋锁 定义自旋锁: spinlock_t lock; 初始化自旋锁: spin_lock_init(lock); 获得自旋锁: spin_lock(lock); 释放自旋锁: spin_unlock(lock); 自旋锁 自旋锁一般用法: spinlock_t lock; //定义一个自旋锁 spin_lock_init(lock); …. spin_lock(lock); //获得自旋锁 …../*临界区*/ spin_unlock(lock); //解锁 自旋锁机制 尽管用了自旋锁可以保证临界区不受别的进程抢占打扰,但是得到锁的代码路径在执行临界区的时候还可能受到中断的影响,为了防止这种影响,就需要用到自旋锁的衍生, 使用自旋锁实现设备只被一个进程打开 int xxx_count =0; static int xxx_open(….) { …… spin_lock(xxx_lock); if(xxx_count) { spin_unlock(xxx_lock); return –EBUSY; } xxx_count++; spin_unlock(xxx_lock); ……… return 0; } 实例引导 在昨天编写的字符设备驱动中加入自旋锁,使设备只能被一个进程打开,并在用户空间里验证。 使用自旋锁应该注意的地方 自旋锁实际上是忙等待,当锁不可用时,CPU一直循环执行“测试并设置”该锁直到可用而取得该锁,CPU在等待自旋锁时不做任何有用的工作,仅仅是等待,因此,只有在占用锁的时间极短的情况下,使用自旋锁才是合理的,当临界区很大或有共享设备的时候,需要较长时间占用锁,使用自旋锁会降低系统性能。 自旋锁可能导致系统死锁,引发这个问题最觉的情况是递归使用一个自旋锁,即如果一个已经拥有某个自旋锁的CPU想第二次获得这个自旋锁,则该CPU将死锁,此外,如果进程获得自旋锁之后再阻塞,也有可能导致死锁的发生,copy_to_user, copy_from_user 和 kmalloc等函数都有可能引起阻塞,因此在自旋锁的占用期间不能调用这些函数。 信号量 信号量是用于保护临界区的一种常用方法,它的使用方式和自旋锁类似。 信号量 获取信号量 void down(struct semaphore *sem); 该函数用于获得信号量sem,它会导致睡
文档评论(0)