<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

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

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

作者: 時(shí)間:2016-12-05 來(lái)源:網(wǎng)絡(luò ) 收藏

  “小王,聽(tīng)說(shuō)過(guò)錦上添花吧..”我拍拍下王的頭說(shuō)。

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

  “還錦上添花你,為你上次提的幾個(gè)東東,我是頭上長(cháng)包..”小王氣憤地瞪著(zhù)我。

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

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

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

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

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

  “小王,給你一個(gè)表現的機會(huì ),說(shuō)說(shuō)這個(gè)和前邊的幾點(diǎn)不同和差異。。”

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

  說(shuō)的好,我只是想強調一點(diǎn):上面三種方式,其實(shí)本身是沒(méi)有優(yōu)劣的,應該根據不同的應用場(chǎng)景合理選擇罷了。

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

  void (*signal(int signo,void (*func)(int))) (int) 這個(gè)看起來(lái)費勁吧,不光你,我看著(zhù)也費勁,沒(méi)關(guān)系,給你來(lái)個(gè)例子:

  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;

  //啟動(dòng)信號驅動(dòng)機制

  signal(SIGIO, sigterm_handler);

  fcntl(STDIN_FILENO, F_SETOWN, getpid());

  oflags = fcntl(STDIN_FILENO, F_GETFL);

  fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);

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

  while(1);

  return 0;

  }

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

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

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

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

  當然,如果你了解linux/Unix信號機制的話(huà),你可能會(huì )問(wèn)為啥沒(méi)說(shuō)sigaction函數,其實(shí)沒(méi)關(guān)系,作用差不多,想知道的話(huà),自己看書(shū)Apue的P261.

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

  在設備驅動(dòng)和應用程序的異步通知交互中,僅僅在應用程序端捕獲信號是不夠的,因為信號沒(méi)有的源頭是在驅動(dòng)端,因此要在適當的時(shí)機讓設備驅動(dòng)釋放信號。

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

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

  2)支持F_SETFL命令的處理,每當FASYNC標志改變時(shí),驅動(dòng)程序中fasync()函數將得以進(jìn)行。因此,驅動(dòng)程序必須實(shí)現fasync()函數。

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

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

  設備驅動(dòng)中異步通知編程還是比較簡(jiǎn)單的,主要就是一些數據結構,和兩個(gè)函數:

  數據結構:fasync_struct結構體

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

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

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

  struct xxx_dev

  {

  struct cdev cdev;

  ...

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

  }

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

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

  }

  一旦設備資源可以獲得時(shí),應該調用kill_fasync()釋放SIGIO信號,可讀時(shí)第三個(gè)參數設置為POLL_IN,可寫(xiě)時(shí)第三個(gè)參數設置為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);

  }

  ..

  }

  最后,在文件關(guān)閉時(shí),即在設備驅動(dòng)的release函數中,應調用設備驅動(dòng)的fasync()函數將文件從異步通知的列表中刪除,下邊是設備驅動(dòng)的釋放函數的典型模版:

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

  {

  struct xxx_dev *dev = filp->private_data;

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

  xxx_fasync(-1,filp,0);

  ...

  return 0;

  }

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



關(guān)鍵詞: Linux 異步I/O

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>