《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 其他 > Linux教學(xué)—— 3 分鐘快速了解信號(hào)驅(qū)動(dòng)式 IO

Linux教學(xué)—— 3 分鐘快速了解信號(hào)驅(qū)動(dòng)式 IO

2022-08-12
來(lái)源:FPGA之家
關(guān)鍵詞: Linux 驅(qū)動(dòng)式IO

  以下是正文:

  一、Linux 的 5 種 IO 模型

  二、如何使用信號(hào)驅(qū)動(dòng)式 I/O?

  三、內(nèi)核何時(shí)會(huì)發(fā)送 "IO 就緒" 信號(hào)?

  四、最簡(jiǎn)單的示例

  五、擴(kuò)展知識(shí)

  一、Linux 的 5 種 IO 模型

  阻塞式 I/O:

  系統(tǒng)調(diào)用可能因?yàn)闊o(wú)法立即完成而被操作系統(tǒng)掛起,直到等待的事件發(fā)生為止。

微信圖片_20220812143203.png

  非阻塞式 I/O (O_NONBLOCK):

  系統(tǒng)調(diào)用則總是立即返回,而不管事件是否已經(jīng)發(fā)生。

微信圖片_20220812143228.png

  I/O 復(fù)用 (select、poll、epoll):

  通過(guò) I/O 復(fù)用函數(shù)向內(nèi)核注冊(cè)一組事件,內(nèi)核通過(guò) I/O 復(fù)用函數(shù)把其中就緒的事件通知給應(yīng)用程序。

微信圖片_20220812143308.png

  信號(hào)驅(qū)動(dòng)式 I/O (SIGIO):

  為一個(gè)目標(biāo)文件描述符指定宿主進(jìn)程,當(dāng)文件描述符上有事件發(fā)生時(shí),SIGIO 的信號(hào)處理函數(shù)將被觸發(fā),然后便可對(duì)目標(biāo)文件描述符執(zhí)行 I/O 操作。

  微信圖片_20220812143329.png

  異步 I/O (POSIX 的 aio_ 系列函數(shù)):

  異步 I/O 的讀寫(xiě)操作總是立即返回,而不論 I/O 是否是阻塞的,真正的讀寫(xiě)操作由內(nèi)核接管。

  微信圖片_20220812143450.png

  思考一下,什么時(shí)候應(yīng)該選擇何種 I/O 模型?為何要這么選擇?

  下面重點(diǎn)關(guān)注信號(hào)驅(qū)動(dòng)式 I/O 這一模型,其他模型可查閱文末參考書(shū)籍。

  二、如何使用信號(hào)驅(qū)動(dòng)式 I/O?

  一般通過(guò)如下 6 個(gè)步驟來(lái)使用信號(hào)驅(qū)動(dòng)式 I/O 模型。

  1> 為通知信號(hào)安裝處理函數(shù)。

  通過(guò) sigaction() 來(lái)完成:

  int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

  默認(rèn)情況下,這個(gè)通知信號(hào)為 SIGIO。

  2> 為文件描述符的設(shè)置屬主。

  通過(guò) fcntl() 的 F_SETOWN 操作來(lái)完成:

  fcntl(fd, F_SETOWN, pid)

  屬主是當(dāng)文件描述符上可執(zhí)行 I/O 時(shí),會(huì)接收到通知信號(hào)的進(jìn)程或進(jìn)程組。

  pid 為正整數(shù)時(shí),代表了進(jìn)程 ID 號(hào)。

  pid 為負(fù)整數(shù)時(shí),它的絕對(duì)值就代表了進(jìn)程組 ID 號(hào)。

  3> 使能非阻塞 I/O。

  通過(guò) fcntl() 的 F_SETFL 操作來(lái)完成:

  flags = fcntl(fd, F_GETFL);

  fcntl(fd, F_SETFL, flags | O_NONBLOCK);

  4> 使能信號(hào)驅(qū)動(dòng) I/O。

  通過(guò) fcntl() 的 F_SETFL 操作來(lái)完成:

  flags = fcntl(fd, F_GETFL);

  fcntl(fd, F_SETFL, flags | O_ASYNC);

  5> 進(jìn)程等待 "IO 就緒" 信號(hào)的到來(lái)。

  當(dāng) I/O 操作就緒時(shí),內(nèi)核會(huì)給進(jìn)程發(fā)送一個(gè)信號(hào),然后調(diào)用在第 1 步中安裝好的信號(hào)處理函數(shù)。

  6> 進(jìn)程盡可能多地執(zhí)行 I/O 操作。

  循環(huán)執(zhí)行 I/O 系統(tǒng)調(diào)用直到失敗為止,此時(shí)錯(cuò)誤碼為 EAGAIN 或 EWOULDBLOCK。

  原因:

  信號(hào)驅(qū)動(dòng) I/O 提供的是邊緣觸發(fā)通知,即只有當(dāng) I/O 事件發(fā)生時(shí)我們才會(huì)收到通知,

  且當(dāng)文件描述符收到 I/O 事件通知時(shí),并不知道要處理多少 I/O 數(shù)據(jù)。

  三、內(nèi)核何時(shí)會(huì)發(fā)送 "IO 就緒" 信號(hào)?

  對(duì)于不同類(lèi)型的文件描述符,情況不一樣。

  1> 終端

  對(duì)于終端,當(dāng)有新的輸入時(shí)會(huì)會(huì)產(chǎn)生信號(hào)。

  2> 管道和 FIFO

  對(duì)于讀端,下列情況會(huì)產(chǎn)生信號(hào):

  數(shù)據(jù)寫(xiě)入到管道中;管道的寫(xiě)端關(guān)閉;

  對(duì)于寫(xiě)端,下列情況會(huì)產(chǎn)生信號(hào):

  對(duì)管道的讀操作增加了管道中的空余空間大小。管道的讀端關(guān)閉;

  3> 套接字

  對(duì)于 UDP 套接字,下列情況會(huì)產(chǎn)生信號(hào):

  數(shù)據(jù)報(bào)到達(dá)套接字;套接字上發(fā)生異步錯(cuò)誤;

  對(duì)于 TCP 套接字,信號(hào)驅(qū)動(dòng)式 I/O 近乎無(wú)用。

  太多情況都會(huì)產(chǎn)生信號(hào),而我們又無(wú)法得知事件類(lèi)型,因此這里就不再列舉其產(chǎn)生信號(hào)的情況。

  四、最簡(jiǎn)單的示例

  信號(hào)處理函數(shù):

  static volatile sig_atomic_t gotSigio = 0;

  static void handler(int sig)

  {

  gotSigio = 1;

  }

  主程序:

  int main(int argc, char *argv[])

  {

  int flags, j, cnt;

  struct termios origTermios;

  char ch;

  struct sigaction sa;

  int done;

  /* Establish handler */

  sigemptyset(&sa.sa_mask);

  sa.sa_flags = SA_RESTART;

  sa.sa_handler = handler;

  if (sigaction(SIGIO, &sa, NULL) == -1) {

  perror("sigaction()\n");

  exit(1);

  }

  /* Set owner process */

  if (fcntl(STDIN_FILENO, F_SETOWN, getpid()) == -1) {

  perror("fcntl() / F_SETOWN\n");

  exit(1);

  }

  /* Enable "I/O possible" signaling and make I/O nonblocking */

  flags = fcntl(STDIN_FILENO, F_GETFL);

  if (fcntl(STDIN_FILENO, F_SETFL, flags | O_ASYNC | O_NONBLOCK) == -1) {

  perror("fcntl() / F_SETFL\n");

  exit(1);

  }

  for (done = 0, cnt = 0; !done ; cnt++) {

  sleep(1);

  if (gotSigio) {

  gotSigio = 0;

  /* Read all available input until error (probably EAGAIN)

  or EOF */

  while (read(STDIN_FILENO, &ch, 1) > 0 && !done) {

  printf("cnt=%d; read %c\n", cnt, ch);

  done = ch == '#';

  }

  }

  }

  exit(0);

  }

  運(yùn)行效果:

  ./build/sigio

  a

  cnt=0; read a

  cnt=0; read

  abc

  cnt=4; read a

  cnt=4; read b

  cnt=4; read c

  cnt=4; read

  #

  cnt=7; read #

  該程序會(huì)先使能信號(hào)驅(qū)動(dòng) IO,然后循環(huán)執(zhí)行計(jì)數(shù)操作。

  當(dāng)有 IO 就緒信號(hào)到來(lái)時(shí),會(huì)去終端讀取數(shù)據(jù)并打印出來(lái),然后繼續(xù)執(zhí)行計(jì)數(shù)操作。

  五、擴(kuò)展知識(shí)

  I/O 多路復(fù)用 、信號(hào)驅(qū)動(dòng) I/O 以及 epoll 機(jī)制可用于監(jiān)視多個(gè)文件描述符。

  它們并不實(shí)際執(zhí)行 I/O 操作,當(dāng)某個(gè)文件描述符處于就緒態(tài),仍需采用傳統(tǒng)的 I/O 系統(tǒng)調(diào)用來(lái)完成 I/O 操作。

  相比 I/O 多路復(fù)用,當(dāng)監(jiān)視大量的文件描述符時(shí)信號(hào)驅(qū)動(dòng) I/O 有著顯著的性能優(yōu)勢(shì),原因是內(nèi)核能夠幫進(jìn)程記錄了正在監(jiān)視的文件描述符列表。

  信號(hào)驅(qū)動(dòng) I/O 的缺點(diǎn):

  信號(hào)的處理流程較為復(fù)雜;

  無(wú)法指定需要監(jiān)控的事件類(lèi)型。

  Linux 特有的 epoll 是一個(gè)更好的選擇。

  六、相關(guān)參考

  UNIX 網(wǎng)絡(luò)編程卷1

  6.2 I/O模型25 信號(hào)驅(qū)動(dòng)式I/O

  Linux-UNIX 系統(tǒng)編程手冊(cè)

  63 其他備選的I/O模型

  Linux 高性能服務(wù)器編程

  8.3 I/O 模型

  Linux 多線程服務(wù)端編程_使用muduo C++網(wǎng)絡(luò)庫(kù)

  7.4.1 muduo的IO模型

  更多信息可以來(lái)這里獲取==>>電子技術(shù)應(yīng)用-AET<<

微信圖片_20210517164139.jpg

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無(wú)法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問(wèn)題,請(qǐng)及時(shí)通過(guò)電子郵件或電話(huà)通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話(huà):010-82306118;郵箱:aet@chinaaet.com。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
一片黄亚洲嫩模| 久久夜色精品| 亚洲精品国产精品国自产在线| 午夜精品网站| 亚洲欧美日韩在线播放| 一本色道久久综合狠狠躁的推荐| 亚洲精品美女免费| 亚洲精品一区二区三区蜜桃久| 亚洲国产中文字幕在线观看| 136国产福利精品导航网址| 曰韩精品一区二区| 亚洲高清一二三区| 91久久夜色精品国产网站| 亚洲韩国青草视频| 亚洲精品乱码久久久久久按摩观| 亚洲黄色一区二区三区| 亚洲欧洲午夜| 99国产一区二区三精品乱码| 99亚洲伊人久久精品影院红桃| 9久re热视频在线精品| 一区二区三区精品视频| 亚洲午夜电影网| 亚洲综合国产精品| 欧美一区二区视频在线观看2020| 欧美在线一区二区三区| 亚洲高清中文字幕| 99精品视频免费在线观看| 在线视频欧美日韩| 亚洲欧美日本精品| 久久久精品国产99久久精品芒果| 久久婷婷色综合| 免费国产一区二区| 欧美乱在线观看| 国产精品九九久久久久久久| 国产欧美日韩激情| 欲色影视综合吧| 亚洲美女福利视频网站| 亚洲午夜精品久久久久久app| 亚洲欧美一区二区三区在线| 久久精品亚洲乱码伦伦中文| 亚洲老板91色精品久久| 亚洲一区免费| 久久精品国产免费看久久精品| 美女黄毛**国产精品啪啪| 欧美日韩免费在线观看| 国产精品一区二区在线| 一区二区三区中文在线观看 | 亚洲欧洲一区二区三区久久| 99精品国产在热久久婷婷| 午夜精品视频一区| 久久综合五月| 欧美偷拍一区二区| 国产偷国产偷精品高清尤物| 亚洲高清视频在线观看| 亚洲午夜精品福利| 91久久国产综合久久91精品网站 | 亚洲一区二区三区中文字幕在线| 欧美在线观看天堂一区二区三区| 免费久久99精品国产自在现线| 欧美日韩的一区二区| 国产伦精品一区二区三区四区免费| 影音先锋一区| 亚洲午夜av在线| 亚洲精品在线视频观看| 羞羞答答国产精品www一本| 毛片一区二区| 国产精品影片在线观看| 亚洲国产婷婷| 欧美一区二区啪啪| 在线一区二区三区四区五区| 久久久久久网址| 国产精品草草| 亚洲国产精品久久人人爱蜜臀| 亚洲影院免费观看| 99国产精品自拍| 久久午夜影视| 国产精品网站视频| 亚洲毛片av在线| 亚洲欧洲日产国产网站| 久久精品91| 欧美午夜激情小视频| 樱桃国产成人精品视频| 午夜精品久久久久久久99热浪潮| 日韩视频免费观看| 久久在线播放| 国产欧美三级| 一区二区三区高清视频在线观看| 亚洲黄色在线看| 久久久精品国产免大香伊| 国产精品乱码妇女bbbb| 亚洲精品1区2区| 亚洲电影免费观看高清完整版在线观看 | 亚洲国内精品| 性8sex亚洲区入口| 一区二区国产日产| 欧美大片在线看| 黄色成人在线网站| 午夜精品一区二区三区在线| 亚洲性感激情| 欧美剧在线观看| 亚洲国产一二三| 亚洲三级电影在线观看| 久久躁日日躁aaaaxxxx| 国产亚洲激情在线| 亚洲欧美在线高清| 午夜在线不卡| 国产精品私拍pans大尺度在线| a91a精品视频在线观看| 一本色道久久| 欧美人与禽猛交乱配视频| 最近中文字幕mv在线一区二区三区四区| 亚洲国产精品福利| 麻豆精品91| 亚洲国产精品日韩| 亚洲精品视频在线播放| 欧美v亚洲v综合ⅴ国产v| 18成人免费观看视频| 亚洲黄网站黄| 欧美刺激性大交免费视频| 在线日韩av永久免费观看| 亚洲国产成人av在线| 久久人人九九| 在线播放亚洲一区| 亚洲精品久久久蜜桃| 欧美精品一区二区三区蜜桃 | 亚洲视频播放| 国产精品成人一区二区网站软件| 一本久久综合| 午夜精品一区二区三区四区| 国产精品久久久久一区| 亚洲综合精品四区| 久久九九99视频| 一区二区三区中文在线观看 | 99视频热这里只有精品免费| 亚洲无亚洲人成网站77777| 国产精品大全| 亚洲图片在线观看| 久久不射2019中文字幕| 国产一区二区三区四区三区四| 欧美在线视频观看| 免费在线观看日韩欧美| 亚洲第一二三四五区| 99精品国产在热久久婷婷| 欧美午夜电影在线观看| 亚洲欧美日韩精品久久| 久久米奇亚洲| 亚洲激情黄色| 亚洲主播在线观看| 国产日韩欧美一区二区三区在线观看| 久久精品夜色噜噜亚洲aⅴ| 欧美激情一区| 亚洲一区二区毛片| 久久综合中文字幕| 亚洲三级性片| 欧美一区二区三区久久精品茉莉花 | 国产精品视频免费| 亚洲欧美国产精品va在线观看 | 日韩午夜电影| 欧美一区二区三区免费看| 亚洲乱码国产乱码精品精可以看 | 99伊人成综合| 久久久777| 91久久极品少妇xxxxⅹ软件| 亚洲一区二区三区在线看| 国产亚洲欧美日韩美女| 日韩亚洲欧美成人| 国产精品日韩精品欧美精品| 久久都是精品| 欧美日韩国产一级| 午夜在线观看欧美| 欧美激情精品久久久六区热门| 中文精品视频| 久久综合久久久| 9色精品在线| 久久久久天天天天| 亚洲精品久久| 久久精品亚洲一区二区| 亚洲黄页视频免费观看| 欧美在线亚洲一区| 亚洲人成在线观看网站高清| 性伦欧美刺激片在线观看| 亚洲盗摄视频| 欧美在线电影| 亚洲精品久久久久久久久久久久 | 噜噜噜在线观看免费视频日韩| 一本色道久久综合狠狠躁篇怎么玩 | 最新热久久免费视频| 欧美三级网址| 亚洲国产日韩欧美综合久久| 国产精品久久久久久久午夜| 亚洲国产综合在线| 国产精品久久久久久久久免费| 亚洲啪啪91| 国产视频在线一区二区 | 久久国产精品电影| 洋洋av久久久久久久一区| 免费亚洲电影在线观看| 亚洲欧美日韩精品久久| 欧美三级中文字幕在线观看| 亚洲激情在线观看视频免费|