在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > Linux內(nèi)核開發(fā)之異步通知與異步I/O(一)

            Linux內(nèi)核開發(fā)之異步通知與異步I/O(一)

            作者: 時間:2016-12-05 來源:網(wǎng)絡 收藏

              “小王,聽說過錦上添花吧..”我拍拍下王的頭說。

            本文引用地址:http://www.biyoush.com/article/201612/341125.htm

              “還錦上添花你,為你上次提的幾個東東,我是頭上長包..”小王氣憤地瞪著我。

              “啊,為啥這樣呢,本來還特意拒絕了MM的約會,抽出時間打算給你說點高級的東東,看來現(xiàn)在是不行了”我吃驚道,“這樣吧,這次就給你講些和前邊有關的東西,也不失為錦上添花不是?”。

              “好,我也是這么打算的,就是沒好意思說,今天講些啥呢?”小王暗淡的眼光總算閃了閃。(為啥這么難受呢,好像跟什么會嚎叫的特像,哈哈)

              那就言歸正傳,今天我們講---設備驅(qū)動程序之異步通知與.”

              小王,前邊不是講了阻塞與非阻塞訪問,poll()函數(shù)等提供的較好的解決設備訪問的機制,那么通過這次有關異步通知整套機制的配合,就更相得益彰,錦上添花了。

              啥叫異步通知:很簡單,一旦設備準備好,就主動通知應用程序,這種情況下應用程序就不需要查詢設備狀態(tài),這是不是特像硬件上常提的“中斷的概念”。上邊比較準確的說法其實應該叫做“信號驅(qū)動的”,信號是在軟件層次上對中斷機制的一種模擬。

              “小王,給你一個表現(xiàn)的機會,說說這個和前邊的幾點不同和差異。。”

              “嗯,我的理解是這樣的哈,阻塞I/O意味著一直等待設備可訪問再訪問,非阻塞I/O意味著使用poll()來查詢是否可訪問,而異步通知則意味著設備通知應用程序自身可訪問。”看著小王聰明的眼睛和清晰的思路,我也忍不住給予一個鼓勵的微笑啊。

              說的好,我只是想強調(diào)一點:上面三種方式,其實本身是沒有優(yōu)劣的,應該根據(jù)不同的應用場景合理選擇罷了。

              說到信號,在應用程序中,為了捕獲信號(還捕獲呢, 不就是一個處理嗎)可以使用signal()函數(shù)來設置對應的信號的處理函數(shù)。函數(shù)原型是

              void (*signal(int signo,void (*func)(int))) (int) 這個看起來費勁吧,不光你,我看著也費勁,沒關系,給你來個例子:

              void sigterm_handler(int signo)

              {

              char data[MAX_LEN];

              int len;

              len=read(STDIN_FILENO, &data,MAX_LEN);

              data[len]=0;

              printf("Input available:%sn",data);

              exit(0);

              }

              int main(void)

              {

              int oflags;

              //啟動信號驅(qū)動機制

              signal(SIGIO, sigterm_handler);

              fcntl(STDIN_FILENO, F_SETOWN, getpid());

              oflags = fcntl(STDIN_FILENO, F_GETFL);

              fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);

              //建立一個死循環(huán),防止程序結束

              while(1);

              return 0;

              }

              看了這段代碼明白啥意思了吧,我也不多少了,咱們繼續(xù)往下走..為了一個用戶在用戶空間中能處理一個設備釋放的信號,它必須完成一下3份工作:

              1)通過F_SETOWN控制指令設置設備文件的擁有者為本進程,這樣從設備驅(qū)動中發(fā)出的信號才能被本進程收到。

              2)通過F_SETFLIO控制命令設置設備文件支持FASYNC,即異步通知模式。

              3)通過signal()鏈接信號和信號處理函數(shù)。

              當然,如果你了解linux/Unix信號機制的話,你可能會問為啥沒說sigaction函數(shù),其實沒關系,作用差不多,想知道的話,自己看書Apue的P261.

              有了信號的發(fā)送,那么就一定得有信號的釋放了:

              在設備驅(qū)動和應用程序的異步通知交互中,僅僅在應用程序端捕獲信號是不夠的,因為信號沒有的源頭是在驅(qū)動端,因此要在適當?shù)臅r機讓設備驅(qū)動釋放信號。

              為了使設備支持異步通知機制,驅(qū)動程序中涉及三個操作:

              1)支持F_SETOWN命令,能在這個控制命令處理中設置filp->f_owner為對應的進程ID。不過此項工作已由內(nèi)核完成,設備驅(qū)動無須處理。

              2)支持F_SETFL命令的處理,每當FASYNC標志改變時,驅(qū)動程序中fasync()函數(shù)將得以進行。因此,驅(qū)動程序必須實現(xiàn)fasync()函數(shù)。

              3)在設備資源可獲得時,調(diào)用kill_fasync()函數(shù)激發(fā)相應的信號。

              驅(qū)動程序中上面的三步是和應用程序是一一對應的。如下圖:

              設備驅(qū)動中異步通知編程還是比較簡單的,主要就是一些數(shù)據(jù)結構,和兩個函數(shù):

              數(shù)據(jù)結構:fasync_struct結構體

              函數(shù):1)處理FASYNC標志變更的函數(shù)int fasync_helper(int fd, struct file *filp, int mode ,struct fasync_struct **fa);

              2) 釋放信號用的函數(shù)void kill_fasync(struct fasync_struct **fa, int sig, int band);

              和其他設備驅(qū)動一樣,一般將fasync_struct放到設備結構體中。下邊是典型模版:

              struct xxx_dev

              {

              struct cdev cdev;

              ...

              struct fasync_struct *async_queue; //異步結構體

              }

              而在驅(qū)動的fasync()函數(shù)中,只需要簡單的將該參數(shù)的3個參數(shù)以及fasync_struct結構體指針的指針作為第四個參數(shù)傳給fasync_helper函數(shù)即可.下邊是典型模版:

              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);

              }

              一旦設備資源可以獲得時,應該調(diào)用kill_fasync()釋放SIGIO信號,可讀時第三個參數(shù)設置為POLL_IN,可寫時第三個參數(shù)設置為POLL_OUT,下邊是釋放信號的典型模版:

              static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_ops)

              {

              struct xxx_dev *dev = filp->private_data;

              ....

              //產(chǎn)生異步信號

              if(dev->async_queue)

              {

              kill_fasync(&dev->async_queue, SIGIO, POLL_IN);

              }

              ..

              }

              最后,在文件關閉時,即在設備驅(qū)動的release函數(shù)中,應調(diào)用設備驅(qū)動的fasync()函數(shù)將文件從異步通知的列表中刪除,下邊是設備驅(qū)動的釋放函數(shù)的典型模版:

              static int xxx_release(struct inode *inode, struct file *filp)

              {

              struct xxx_dev *dev = filp->private_data;

              //將文件從異步通知列表中刪除

              xxx_fasync(-1,filp,0);

              ...

              return 0;

              }

              “等等,我知道你明白,你是想向我個例子,我知道你啥意思,沒關系,我下次補上 。”沒等小王,我立刻給她堵上“你啊,心里幾根小九九,我還不知道啊..”



            關鍵詞: Linux 異步I/O

            評論


            相關推薦

            技術專區(qū)

            關閉