日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

linux异步IO

發布時間:2023/12/10 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux异步IO 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

異步IO

回顧同時讀鍵盤、鼠標的方法

  • 多進程
  • 多線程
  • 將“讀鼠標”和“讀鍵盤”設置為非阻塞
  • 多路IO(select、poll機制)
  • 異步IO
  • 異步IO的原理

    前面四種方式都是主動去讀,對于read函數來說它并不知道是不是一定有數據,如果有數據就讀到數據,沒有數據要么阻塞直到讀到數據為止,要么不阻塞。

    這就好比我想去澡堂洗澡,我不知道有沒有位置,我去了后如果有位置我就立即洗澡(立即讀數據),如果沒有位置要么等(阻塞讀),要么離開過段時間再來看(非阻塞讀)。

    實際上除了以上描述符的方式外,還有另外一種聰明的方式,那就是使用異步IO的方式來實現。

    異步IO的原理就是,底層把數據準備好后,內核就會給進程發送一個“異步通知的信號”通知進程,表示數據準備好了,然后調用信號處理函數去讀數據,在沒有準備好時,進程忙自己的事情。

    這就好比我跟澡堂老板說一聲“有位置了打電話給我哈”,我就會去該干嘛就干嘛,等老板通知我了我就知道有位置了,這樣的方式不就更好嗎?

    比如使用異步IO讀鼠標,底層鼠標驅動就把數據準備好后,會發一個“SIGIO”(異步通知的信號)給進程,進程調用捕獲函數讀鼠標,讀鼠標的SIGIO捕獲函數需要我們自己定義。

    使用異步IO方式讀鼠標讀鍵盤

    進程正常阻塞讀鍵盤,然后將讀鼠標設置為異步IO方式。

    進程正常阻塞讀鍵盤時,如果鼠標沒有數據的話,進程不關心讀鼠標的事情,如果鼠標數據來了,底層鼠標驅動會向

    進程發送一個SIGIO信號,然后調用注冊的SIGIO信號捕獲函數讀鼠標數據。

    當然也可以反過來,進程正常阻塞讀鼠標,然后將讀鍵盤設置為異步IO方式。

    異步IO這個名字怎么理解?

    比如以異步IO方式讀鼠標數據為例,如果知道什么時候數據會來,等這個時間到時再去讀數據,這就是步調統一的同步讀。

    如果不知道什么時候會有數據來,這種就只能是什么時候數據來了就什么時候讀,這種就是異步讀。

    之所以叫異步,是因為我不知道你什么時候來,沒辦法統一步調(異步的),只能是隨時來隨時讀

    使用異步IO要有兩個前提

  • 底層驅動必須要有相應的發送SIGIO信號的代碼,只有這樣當底層數據準備好后,底層才會發送SIGIO信號給進程。
  • 我們之所以可以對鼠標設置異步IO,是因為人家在實現鼠標驅動時,有寫發送SIGIO信號的代碼,如果驅動程序時我們自己寫的,發送SIGIO的代碼就需要我們自己來寫。
  • 應用層必須進行相應的異步IO設置,否則后者無法使用異步IO。
    應用層進行異步IO設置時,使用的也是fcntl函數。
  • 使用異步IO,應用層的設置步驟

  • 調用signal函數對SIGIO信號設置捕獲函數

    • 在捕獲函數里面實現讀操作,比如讀鼠標。
  • 使用fcntl函數,將接收SIGIO信號的進程設置為當前進程

    • 如果不設置,底層驅動并不知道將SIGIO信號發送給哪一個進程
    • fcntl(mousefd, F_SETOWN, getpid()); /* 將當前進程的進程號告訴給內核 */

    F_GETOWN

    獲取當前在文件描述符 fd上接收到SIGIO 或 SIGURG事件信號的進程ID或進程組,arg忽略。

    F_SETOWN

    設置在文件描述符fd上接收SIGIO 或 SIGURG事件信號的進程ID或進程組ID,值為arg。

  • 使用fcntl函數,對文件描述符增設O_ASYNC的狀態標志,讓fd支持異步IO

    • mousefd = open("/dev/input/mouse1", O_RDONLY);
    • flag = fcntl(mousefd, F_GETFL);
    • flag |= O_ASYNC; //補設O_ASYNC
    • fcntl(mousefd, F_SETFL, flag);/* 設置進程啟用異步通知功能 */
  • 代碼演示:

    void signal_fun(int signo) {int buf;int ret = 0;if (SIGIO == signo){bzero(&buf, sizeof(buf));ret = read(mousefd, &buf, sizeof(buf));if (ret > 0) printf("%d\n", buf);} }int main(int argc, char *argv[]) {int ret = 0;char buf[100] = {0};struct pollfd fds[2];mousefd = open("/dev/input/mouse0", O_RDONLY);if (mousefd == -1) print_err("open /dev/input/mouse0 fail", __LINE__, errno);/* 為SIGIO設置捕獲函數,在捕獲函數里面讀鼠標 */signal(SIGIO, signal_fun);/* 告訴鼠標驅動,它發送的SIGIO信號由當前進程接收 */fcntl(mousefd, F_SETOWN, getpid());/* 對mousefd進行設置讓其支持異步IO */int flag = fcntl(mousefd, F_GETFL);flag |= O_ASYNC;fcntl(mousefd, F_SETFL, flag);while(1){bzero(buf, sizeof(buf));ret = read(0, buf, sizeof(buf));if (ret > 0) printf("%s\n", buf);}return 0; }

    總結

    以上是生活随笔為你收集整理的linux异步IO的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。