linux设备驱动中的并发控制

{//?什么是并发,为何要使用并发机制
	并发即是 多件事情同时在执行
	
  只有使这些设备都并发的执行才能满足性能要求。  
  
  例:
      如果系统上挂10个设备,每个设备都请求,如果是串行顺序执行,
      可能一个设备要等较长时间,系统才能响应它    
}	
{//?如何实现并发
	CPU是顺序的读入指令执行的, 如何来实现并发呢?	
	例:
	   当你A先生的业务时,B女士来个电话,你接完电话后继续做A的事。
	   如何你切换足够快,即在A,B的忍耐时间内。 感觉就像在并发执行一样。
	   
	使用中断的方式可实现并发    //中断: 类似于接电话,打断当前执行,等处理完后,返回再接着执行。
	     
}
{//?为什么要进行并发控制
	并发会导致竞态的发生。 //竞态: 一个资源被并发执行的任务同时访问时,就会出现竞争。此时的状态就是竞态。
	需保证一个资源在一个时间只能被一个任务访问,才能避免混乱。即并发控制	
}	


{//?如何进行并发控制
 采用互斥机制对并发进行控制  //互斥: 共享资源被某任务访问时,别的任务禁止访问。
	                                                                                             
 互斥机制:
	 {//中断屏蔽     
	 	 使用禁止中断方式,避免中断的影响 
	 	 
	 	 local_irq_disable       //屏蔽中断
	 	 临界区代码              //临界区: 访问共享资源的代码区域
	 	 local_irq_enable        //开中断
	 	 
	 	 注: 
	 	    1。屏蔽中断的时间尽量短,否则会造成别的中断延时过久,甚至丢失,最好能采有屏蔽指定中断的方式
	 	 		  disable_irq(int irq); //屏蔽指定中断号的中断
			    enable_irq(int irq);  //使能某中断号的中断   
			  2。常需保存当前的中断状态,便于恢复   
			    用local_irq_save(flags);  代替local_irq_disable
			    用local_irq_restore(flags) 代替 local_irq_enable			  
   }	      
	 {//原子操作
	 	 并发中不被打断的最小单元
	 	
	  {//---hello_atomic/hello.c         实现设备只被一个进程打开
	  	#include <asm/atomic.h>
	  	
		  static atomic_t hello_atomic = ATOMIC_INIT(1);    //定义原子变量hello_atomic ,并初始化为1 
	    static int hello_open(struct inode *inode,struct file *file)
	    {
	      if (!atomic_dec_and_test(&hello_atomic))  {  //  atomic_dec_and_test表示原子变量自减一,并测试是否为了零,如果为零返回真
	      	 //当已open过,还未release时,再次open , hello_atomic为0, 再减一不为零,!atomic_dec_and_test 成立  
	         atomic_inc(&hello_atomic);       //原子变量加一,恢复自减前状态
	         return  - EBUSY;   //已经被打开
	      }
	      //当第一次被open时, hello_atomic为1  , !atomic_dec_and_test 不成立, 正常打开
	      printk("hello open \n");
	      return 0;
	    } 
	    static int hello_release(struct inode *inode,struct file *file)
	    { 
	      atomic_inc(&hello_atomic);   //释放设备    
	      printk("hello release\n");
	      return 0;
	    }
    }	
	 	
   }   
	 {//自旋锁	spinlock
	 	 死循环空转CPU 等待释放锁,  不睡眠, 适用于锁持有时间小于睡眠唤醒时间场合	
	 	 	
	 	 {//---hello_spinlock/hello.c
 			static spinlock_t hello_spinlock; 
 			static int hello_resource = 1;
 			
 			static int hello_open(struct inode *inode,struct file *file)
 			{
 			  spin_lock(&hello_spinlock);  //还可和中断屏蔽合用 spin_lock_irq
 			  if(hello_resource == 0)
 			  {
 			     spin_unlock(&hello_spinlock); 
 			     return  - EBUSY; 
 			  }
 			  hello_resource--;
 			  spin_unlock(&hello_spinlock); 
 			
 			
 			  printk("hello open \n");
 			  return 0;
 			} 
 			static int hello_release(struct inode *inode,struct file *file)
 			{
 			  spin_lock(&hello_spinlock);
 			  hello_resource++; 
 			  spin_unlock(&hello_spinlock);
 			
 			  printk("hello release\n");
 			  return 0;
 			}
     }
     
	 	 {//读写锁 rwlock_t      
	 	 	   它是从资源访问的特性上,对锁进行了优化, 读可同时进行 ,读写互斥
     }
     
	 	 {//顺序锁 seqlock       
	 	 	  它是对读写锁的进一步优化,放开了读写互斥, 即仅写间互斥。即使读者正在读的时候也允许写者继续运行
	   }
	   
	   {//无锁设计     
	   	   如环形缓冲   类似生产者和消费者模型
	   }
	   
	   //加锁粒度
   }   
	 {//信号量
 	  进程当中用于并发互斥和,资源的计数。
 	  相对于自旋锁,信号量会睡眠,仅能用于进程中 
    //---hello_semaphore/hello.c
  	#include <linux/semaphore.h>
    static DECLARE_MUTEX(hello_semlock);   //定义一个初始值为一的信号量
       
    static int hello_open(struct inode *inode,struct file *file)
    {              
      if (down(&hello_semlock))  /* 获得打开锁*/
      {
         return  - EBUSY;  /* 设备忙*/
      }
      printk("hello open \n");
      return 0;
    }
    static int hello_release(struct inode *inode,struct file *file)
    {
      up(&hello_semlock);  /* 释放打开锁*/
      printk("hello release\n");
      return 0;
    }	  
   }    
 	 {//互斥体
  	 互斥体是专门用来做互斥的, 和二元的信号量类似, 
  	
		struct mutex my_mutex;  /* 定义mutex */
		mutex_init(&my_mutex);  /* 初始化mutex */
		
		mutex_lock(&my_mutex);  /* 获取mutex */
		.../* 临界资源*/
		mutex_unlock(&my_mutex); /* 释放mutex */
   }	
   
  
}

{//?并发机制使用场合

	1. 中断屏蔽的使用场合
	   当有中断处理程序访问共享资源的时候。
	2. 原子操作的使用场合
	   只使用于共享资源为一个变量的操作的情况
	3. 自旋锁的使用场合
	   在临界区代码运行时间比较短的情况。
	   多CPU的情况下 
	4. 信号量的使用场合
	   临界区代码运行时间比较长的情况。  
	   当锁持有的时间不是很长的时候,优先使用信号量。
	   1注意: 中断里不能使用信号量。 因为中断不能睡眠。
}	
			
}

linux设备驱动中的并发控制,布布扣,bubuko.com

linux设备驱动中的并发控制

上一篇:linux下更改ip和mac命令


下一篇:linux内核链表使用