Linux 設備驅動--- 並發 與 競態 --- atomic_t --- atomic_dec_and_test --- 原子操作


並發:

          多個執行單元同時被執行.


競態:

          並發的執行單元對資源 ( 硬件資源和軟件上的全局變量等 ) 的訪問導致的競爭狀態.

          


並發的處理:

          處理並發的常用技術是加鎖或者互斥,即保證在任何時間只有一個執行單元可以操作共享資源.

          在 Linux 內核中主要通過 semaphore 機制 (信號量)和spin_lock 機制 (自旋鎖)實現.


原子操作:

定義:

原子操作指的是在執行過程中不會被別的代碼所中斷的操作.

分為 位 和 整型變量 兩類原子操作。


atomic_t  :

  1. typedef struct {  
  2. volatile int counter;  
  3. } atomic_t;  

原子操作函數:

整型原子操作:

  1. void atomic_set(atomic_t *v, int i);   //設置原子變量v的值為i  
  2. atomic_t v = ATOMIC_INIT(0);            //定義原子變量v, 並初始化為0  **************************  
  3. atomic_read(atomic_t *v);              //獲得原子變量的值,返回原子變量的值  
  4. void atomic_add(int i, atomic_t *v);    //原子變量+i  
  5. void atomic_sub(int i, atomic_t *v);    //原子變量-i  
  6. void atomic_inc(atomic_t *v);           //原子變量+1            *******************************  
  7. void atomic_dec(atomic_t *v);           //原子變量-1  

 

對原子變量執行自增,自減和減操作后 ,測試其是否為0,為 0 則返回 true,否則返回 false :

  1. int atomic_inc_and_test(atomic_t *v);   
  2. int atomic_dec_and_test(atomic_t *v);              ***********************  
  3. int atomic_sub_and_test(int i, atomic_t *v);          


對原子變量進行加/減,自增/自減操作,並返回新的值:

  1. int atomic_add_return(int i, atomic_t *v);  
  2. int atomic_sub_return(int i, atomic_t *v);  
  3. int atomic_inc_return(atomic_t *v);  
  4. int atomic_sub_return(atomic_t *v);  

位原子操作:

  1. void set_bit(nr, void *addr);    //將addr地址的nr位 置為1  
  2. void clear_bit(nr, void *addr);  //將addr地址的nr位 清0  
  3. void change_bit(nr, void *addr);  //對addr地址的nr位 反置  
  4. int test_bit(nr, void *addr);    //返回addr地址的nr位  
  5. int test_and_set_bit(nr, void *addr);  
  6. int test_and_clear_bit(nr, void *addr);  
  7. int test_and_change_bit(nr, void *addr);  
  8. 先設值,后返回。  



實例 --- 原子操作:

1,定義一原子變量:

在程序開頭定義原子變量,初始化為 1 :

  1. static atomic_t canopen = ATOMIC_INIT(1);     //定義原子變量並初始化為1  

 

2,在 open 函數里檢測原子變量值:

如果減 一 為 0 , !true 為 假 ,if 里面的原子變量加一恢復到  0

  • {  
  •     atomic_inc(&canopen);  
  •     return -EBUSY;  
  • }  

 

3,在退出時 close 函數 恢復原子變量值:

最后, 在應用程序退出時 close 函數, 自增 恢復原子變量值為 1:

  1. atomic_inc(&canopen);  

 

4,應用程序測試:

在應用程序里面打開驅動程序:

  1. fd = open("/dev/buttons", O_RDWR);  
  2. if (fd < 0)  
  3. {  
  4.     printf("can't open!\n");  
  5.     return -1;  
  6. }  


當有兩個應用程序打開同一這個驅動的時候,打印 can't open! .


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM