日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux :IO多路复用模型

發(fā)布時(shí)間:2023/11/30 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux :IO多路复用模型 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載:http://blog.csdn.net/mr253727942/article/details/50827127

一、IO多路復(fù)用定義

IO多路復(fù)用允許應(yīng)用在多個(gè)文件描述符上阻塞,并在某一個(gè)可以讀寫時(shí)通知, 一般遵循下面的設(shè)計(jì)原則:、

  • IO多路復(fù)用:任何文件描述符準(zhǔn)備好IO時(shí)進(jìn)行通知
  • 在文件描述符就緒前進(jìn)行睡眠。
  • 喚醒:哪個(gè)準(zhǔn)備好了
  • 在不阻塞的情況下處理所有IO就緒的文件描述符
  • 返回第一步
  • Linux下提供了三種IO多路復(fù)用方案,select、poll和epoll。

    二、select IO 多路復(fù)用

    看一下select 函數(shù)的定義:

    int select (int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);FD_CLR(int fd, fd_set *set);FD_ISSET(int fd, fd_set *set);FD_SET(int fd, fd_set *set);FD_ZERO(fd_set *set);

    上面的定義中可以看到select主要檢測三類文件描述符,分別等待不同的事件。

    • readfds

      確認(rèn)是否有可讀數(shù)據(jù)
    • writefds

      確認(rèn)是否有可寫數(shù)據(jù)
    • exceptefds

      確認(rèn)是否有異常發(fā)生或者出現(xiàn)帶外數(shù)據(jù)。

    第一個(gè)參數(shù)n,等于所有集合中文件描述符的最大值加一。select()的調(diào)用者需要找到最大的文件描述符值加一作為第一個(gè)參數(shù)。

    成功返回時(shí),返回哪一個(gè)文件描述符,就說明該文件描述符準(zhǔn)備好無阻塞IO。對于timeout,select操作可以設(shè)置一個(gè)超時(shí)時(shí)間,超時(shí)后即使沒有文件描述符IO就緒也會(huì)返回。

    select的缺點(diǎn):

    1.每次調(diào)用select,都需要把fd集合從用戶態(tài)拷貝到內(nèi)核態(tài)?
    2。同時(shí)需要遍歷所有fd?
    3。支持的文件描述符默認(rèn)只有1024

    三、poll IO 多路復(fù)用

    poll()系統(tǒng)調(diào)用也是一個(gè)IO多路復(fù)用解決方案,解決了 一些select的不足,下面給出poll的定義:

    #include <sys/poll.h> int poll (struct pollfd *fds, unsigned int nfds, int timeout);

    與上面的select()使用三個(gè)文件描述符集合不同,poll()使用了一個(gè)簡單的nfds個(gè)pollfd結(jié)構(gòu)體構(gòu)成的數(shù)組,fds指向該數(shù)組,結(jié)構(gòu)體定義如下:

    #include <sys/poll.h> struct pollfd {int fd; /* file descriptor */short events; /* requested events to watch */short revents; /* returned events witnessed */ };

    每個(gè)pollfd指定了唯一一個(gè)文件描述符,每個(gè)結(jié)構(gòu)體中的events字段是要堅(jiān)實(shí)的文件描述符事件的一組位掩碼。revents字段是發(fā)生在該文件描述符上的事件的位掩碼,內(nèi)核在返回時(shí)設(shè)置這個(gè)字段,所有events字段請求的時(shí)間都可能在revents字段中返回。下面是合法的事件:

    POLLIN 沒有數(shù)據(jù)可讀 POLLRDNORM 有正常數(shù)據(jù)可讀。 POLLRDBAND 有優(yōu)先數(shù)據(jù)可讀。 POLLPRI 有高優(yōu)先級數(shù)據(jù)可讀。 POLLOUT 寫操作不會(huì)阻塞。 POLLWRNORM 寫正常數(shù)據(jù)不會(huì)阻塞。 POLLBAND 寫優(yōu)先數(shù)據(jù)不會(huì)阻塞。 POLLMSG 有一個(gè)sigpoll消息可用。

    除此之外還可能返回幾個(gè)異常信息:

    POLLER 文件描述符有錯(cuò)誤。 POLLHUP 文件描述符上有掛起事件。 POLLNVAL 給出的文件描述符非法。

    監(jiān)視一個(gè)文件描述符是否可以讀寫,可以設(shè)置events為POLLIN | POLLOUT,返回時(shí)將在revents中檢查是否有相應(yīng)標(biāo)志。如果設(shè)置了POLLIN,或者POLLOUT則代表可以操作相關(guān)事件。

    timeout參數(shù)指定在任何IO就緒前需要等待時(shí)間的長度,負(fù)值表示永遠(yuǎn)等待,一個(gè)零值表示調(diào)用立即返回,列出所有為準(zhǔn)備好的IO,不等待任何時(shí)間。

    四、poll()與select()的區(qū)別

    poll()系統(tǒng)調(diào)用優(yōu)于select():

    • poll()不需要使用者計(jì)算最大的文件描述符值加一和傳遞該參數(shù)。
    • poll()在應(yīng)對較大值的文件描述符時(shí)效率更好,如果用select()監(jiān)視值為900的文件描述符–內(nèi)核需要檢查每個(gè)集合中的每個(gè)bit位,知道第九百個(gè)。
    • select()的文件描述符集合是靜態(tài)大小,但是poll()可以創(chuàng)建合適大小的數(shù)組,只需要傳遞結(jié)構(gòu)體數(shù)組即可。
    • select()文件描述符集合會(huì)在返回時(shí)重新創(chuàng)建,每個(gè)調(diào)用都必須要重新初始化它們。poll()系統(tǒng)調(diào)用分離了events字段和revents字段,無需改變就能重用。
    • 相對于poll(),select()移植性更好
    • select()提供了更好的超時(shí)方案。

    五、epoll IO 多路復(fù)用

    上面的兩種方式中,每次調(diào)用都需要所有被監(jiān)聽的文件描述符,內(nèi)核必須遍歷所有的文件描述符,當(dāng)文件描述符變得很大,這里的遍歷就會(huì)成為瓶頸。

    epoll將監(jiān)聽注冊從實(shí)際監(jiān)聽中分離出來,完成了真正的事件等待。

    1、先創(chuàng)建一個(gè)新的epoll實(shí)例:

    #include <sys/epoll.h> int efpd = epoll_create (int size)

    size是告訴內(nèi)核大概需要監(jiān)聽的文件描述符數(shù)目。

    2、控制epoll

    epoll_ctl()可以向指定的epoll上下文中加入或刪除文件描述符。

    #include <sys/epoll.h> int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);

    頭文件

    六、IO實(shí)現(xiàn)的內(nèi)核內(nèi)幕

    主要涉及三個(gè)內(nèi)核子系統(tǒng):

  • 虛擬文件系統(tǒng)(VFS)
  • 頁緩存
  • 頁回寫
  • 虛擬文件系統(tǒng)

    虛擬文件系統(tǒng)是linux內(nèi)核的文件操作的抽象機(jī)制,允許內(nèi)核在無需了解文件系統(tǒng)類型的情況下,使用文件系統(tǒng)函數(shù)和操作文件系統(tǒng)數(shù)據(jù)。

    VFS實(shí)現(xiàn)這種抽象的方法是使用一種通用文件模型,它是所有l(wèi)inux文件系統(tǒng)的基礎(chǔ),通用文件模型提供了linux內(nèi)核文件系統(tǒng)必須遵循的框架,框架提供了了hooks支持讀寫、建立鏈接、同步等其他功能。

    當(dāng)然這種方法規(guī)定了一些共性,比如必須要有inode,super block(超級塊)和目錄條目等。

    頁緩存

    頁緩存是一種在內(nèi)存中保存最近在磁盤文件系統(tǒng)上訪問過的數(shù)據(jù)的方式。頁緩存是內(nèi)核尋找文件系統(tǒng)數(shù)據(jù)的第一目的地。只有緩存找不到時(shí)內(nèi)核才會(huì)調(diào)用存儲(chǔ)子系統(tǒng)從磁盤讀數(shù)據(jù)。

    linux中頁緩存大小是動(dòng)態(tài)的,隨著IO操作將越來越多的數(shù)據(jù)帶入內(nèi)存,頁緩存會(huì)隨之增大,消耗更多的內(nèi)存,如果頁緩存確實(shí)消耗掉了所有空閑內(nèi)存,頁緩存會(huì)釋放最少使用頁。

    頁回寫

    內(nèi)核使用緩沖區(qū)來延遲寫操作,當(dāng)一個(gè)進(jìn)程發(fā)起寫請求,數(shù)據(jù)被拷貝到緩沖區(qū),這時(shí)將緩沖區(qū)標(biāo)記為“臟”數(shù)據(jù),如果對同一個(gè)數(shù)據(jù)塊有新的寫請求,緩沖區(qū)就更新為新數(shù)據(jù),把“臟”緩沖區(qū)寫入磁盤。有兩個(gè)條件會(huì)觸發(fā)這種回寫:

  • 當(dāng)空閑內(nèi)存小于設(shè)定的閥值,會(huì)將緩沖區(qū)回寫。
  • 當(dāng)一個(gè)臟的緩沖區(qū)壽命超過閥值也會(huì)回寫防止數(shù)據(jù)不確定。
  • 回寫由一些pdflush內(nèi)核線程操作,當(dāng)上述兩種情況發(fā)生,線程被喚醒開始刷新臟緩沖區(qū)。


    總結(jié)

    以上是生活随笔為你收集整理的Linux :IO多路复用模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。