linux驅動程式中的非同步編程

來源:互聯網
上載者:User

標籤:

linux驅動程式中的非同步編程

A
前面介紹的等待隊列和輪詢編程提供了較好的解決裝置訪問的機制,但是這些機制都
是由應用程式發起的,都需要應用程式主動訪問裝置。更完美的方式是由驅動程式主
動通知應用程式,也就是說,當驅動程式滿足某些條件後,會主動通知應用程式處理
,這些處理方式有些像物件導向編程的事件,而在linux核心使用的事件是接下來要介
紹的訊號。
#include<sys/types.h>  
#include<sys/stat.h>  
#include<stdio.h>  
#include<fcntl.h>  
#include<signal.h>  
#include<unistd.h>  
#define MAX_LEN 100 
 
void input_handler(int num)  //捕獲處理函數
{  
    char data[MAX_LEN];  
    int len;  
  
    len=read(STDIN_FILENO,&data,MAX_LEN);  
    data[len]=0;  
    printf("input available:%s\n",data);  
}  
  


main()  
{  
    int oflags;  
    
    signal(SIGIO,input_handler);   //捕獲SIGIO訊號
    //通過F_SETOWN將標準輸入裝置檔案(驅動)STDIN_FILENO--的擁有者設定為
   //當前進程,這樣從裝置驅動STDIN_FILENO發出的訊號才能被當前進程所接到。
    fcntl(STDIN_FILENO,F_SETOWN,getpid());  
    oflags=fcntl(STDIN_FILENO,F_GETFL); 
   // 通過F_SETFL使裝置檔案支援FASYNC,也就是非同步通知模式。
    fcntl(STDIN_FILENO,F_SETFL,oflags|FASYNC);  
  
    while(1);  
}  


B
裝置驅動中非同步通知編程比較簡單,主要用到一項資料結構和兩個函數。
資料結構是 fasync_struct 結構體,
兩個函數分別如下。 
處理 FASYNC 標誌變更的函數。 
int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa); 
釋放訊號用的函數。 
void kill_fasync(struct fasync_struct **fa, int sig, int band); 
和其他的裝置驅動一樣,將 fasync_struct 結構體指標放在裝置結構體中仍然是最
佳選擇,代碼清單給出了支援非同步通知的裝置結構體模板。
struct xxx_dev   
  {   
      struct cdev cdev; /*cdev 結構體*/   
        ...   
      struct fasync_struct *async_queue; /* 非同步結構體指標 */   
 };   
在裝置驅動的 fasync() 函數中,只需要簡單地將該函數的 3 個參數以及
fasync_struct 結構體指標的指標作為第 4 個參數傳入 fasync_helper()函數即

可。代碼清單給出了支援非同步通知的裝置驅動程式 fasync()函數的模板。

//處理應用程式的F_SETFL命令的fasync函數

 static int xxx_fasync(int fd, struct file *filp, int mode)   
{   
     struct xxx_dev *dev = filp->private_data;    
     return fasync_helper(fd, filp, mode, &dev->async_queue);   
 }   
static  struct file_operations dev_fops=
{
.owner=...
.read=....
.write=...
.fasync=xxx_fasync;
}
在裝置資源可以獲得時,應該調用 kill_fasync()釋放 SIGIO 訊號,可讀時第 3 
個參數設定為 POLL_IN,可寫時第 3 個參數設定為 POLL_OUT。下面代碼為釋放訊號
的範例。
static ssize_t xxx_write(struct file *filp, const char _ _user *buf, size_t count,loff_t *f_pos}
       {   
   struct xxx_dev *dev = filp->private_data;   
   ...   
   
  if (dev->async_queue)   
     kill_fasync(&dev->async_queue, SIGIO, POLL_IN);   /* 產生非同步讀訊號 */   
   ...   
 }   

最後,在檔案關閉時,即在裝置驅動的 release()函數中,應調用裝置驅動的 
fasync()函數將檔案從非同步通知的列表中刪除。下面代碼清單給出了支援非同步通知的
裝置驅動release()函數的模板。
static int xxx_release(struct inode *inode, struct file *filp)   
  {   
    struct xxx_dev *dev = filp->private_data;   
   /* 將檔案從非同步通知清單中刪除 */   
   xxx_fasync(-1, filp, 0);   
   ...   
    return 0;   

  }   


應用程式:

開啟兩個終端,一個運行應用程式,另外一個執行 echo   "hello" >/dev/裝置名稱  ,

執行完這條指令後,驅動調用write函數,驅動程式中的write函數中會調用

kill_fasync(&dev->async_queue, SIGIO, POLL_IN);   /* 產生非同步讀訊號 */ ,

這樣應用程式馬上捕捉到SIGIO,此時應用程式進入處理接受訊號函數。





linux驅動程式中的非同步編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.