• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-80  評(píng)論-24  文章-0  trackbacks-0
            select()函數(shù)和poll()函數(shù)均是主要用來(lái)處理多路I/O復(fù)用的情況。比如一個(gè)服務(wù)器既想等待輸入終端到來(lái),又想等待若干個(gè)套接字有客戶請(qǐng)求到達(dá),這時(shí)候就需要借助select或者poll函數(shù)了。

            (一)select()函數(shù)

            原型如下:

            1 int select(int fdsp1, fd_set *readfds, fd_set *writefds, fd_set *errorfds, const struct timeval *timeout);

            各個(gè)參數(shù)含義如下:
            • int fdsp1:最大描述符值 + 1
            • fd_set *readfds:對(duì)可讀感興趣的描述符集
            • fd_set *writefds:對(duì)可寫(xiě)感興趣的描述符集
            • fd_set *errorfds:對(duì)出錯(cuò)感興趣的描述符集
            • struct timeval *timeout:超時(shí)時(shí)間(注意:對(duì)于linux系統(tǒng),此參數(shù)沒(méi)有const限制,每次select調(diào)用完畢timeout的值都被修改為剩余時(shí)間,而unix系統(tǒng)則不會(huì)改變timeout值)
            select函數(shù)會(huì)在發(fā)生以下情況時(shí)返回:
            1. readfds集合中有描述符可讀
            2. writefds集合中有描述符可寫(xiě)
            3. errorfds集合中有描述符遇到錯(cuò)誤條件
            4. 指定的超時(shí)時(shí)間timeout到了
            當(dāng)select返回時(shí),描述符集合將被修改以指示哪些個(gè)描述符正處于可讀、可寫(xiě)或有錯(cuò)誤狀態(tài)。可以用FD_ISSET宏對(duì)描述符進(jìn)行測(cè)試以找到狀態(tài)變化的描述符。如果select因?yàn)槌瑫r(shí)而返回的話,所有的描述符集合都將被清空。
            select函數(shù)返回狀態(tài)發(fā)生變化的描述符總數(shù)。返回0意味著超時(shí)。失敗則返回-1并設(shè)置errno。可能出現(xiàn)的錯(cuò)誤有:EBADF(無(wú)效描述符)、EINTR(因終端而返回)、EINVAL(nfds或timeout取值錯(cuò)誤)。
            設(shè)置描述符集合通常用如下幾個(gè)宏定義:

            1 FD_ZERO(fd_set *fdset);                /* clear all bits in fdset           */
            2 FD_SET(int fd, fd_set *fdset);         /* turn on the bit for fd in fd_set  */
            3 FD_CLR(int fd, fd_set *fdset);         /* turn off the bit for fd in fd_set */
            4 int FD_ISSET(int fd, fd_set *fdset);   /* is the bit for fd on in fdset?    */

            如:

            1 fd_set rset;
            2 FD_ZERO(&rset);                        /* initialize the set: all bits off  */
            3 FD_SET(1&rset);                      /* turn on bit for fd 1              */
            4 FD_SET(4&rset);                      /* turn on bit for fd 4              */
            5 FD_SET(5&rset);                      /* turn on bit for fd 5              */

            當(dāng)select返回的時(shí)候,rset位都將被置0,除了那些有變化的fd位。
            當(dāng)發(fā)生如下情況時(shí)認(rèn)為是可讀的:
            1. socket的receive buffer中的字節(jié)數(shù)大于socket的receive buffer的low-water mark屬性值。(low-water mark值類似于分水嶺,當(dāng)receive buffer中的字節(jié)數(shù)小于low-water mark值的時(shí)候,認(rèn)為socket還不可讀,只有當(dāng)receive buffer中的字節(jié)數(shù)達(dá)到一定量的時(shí)候才認(rèn)為socket可讀)
            2. 連接半關(guān)閉(讀關(guān)閉,即收到對(duì)端發(fā)來(lái)的FIN包)
            3. 發(fā)生變化的描述符是被動(dòng)套接字,而連接的三路握手完成的數(shù)量大于0,即有新的TCP連接建立
            4. 描述符發(fā)生錯(cuò)誤,如果調(diào)用read系統(tǒng)調(diào)用讀套接字的話會(huì)返回-1。
            當(dāng)發(fā)生如下情況時(shí)認(rèn)為是可寫(xiě)的:
            1. socket的send buffer中的字節(jié)數(shù)大于socket的send buffer的low-water mark屬性值以及socket已經(jīng)連接或者不需要連接(如UDP)。
            2. 寫(xiě)半連接關(guān)閉,調(diào)用write函數(shù)將產(chǎn)生SIGPIPE
            3. 描述符發(fā)生錯(cuò)誤,如果調(diào)用write系統(tǒng)調(diào)用寫(xiě)套接字的話會(huì)返回-1。
            注意:
            select默認(rèn)能處理的描述符數(shù)量是有上限的,為FD_SETSIZE的大小。
            對(duì)于timeout參數(shù),如果置為NULL,則表示wait forever;若timeout->tv_sec = timeout->tv_usec = 0,則表示do not wait at all;否則指定等待時(shí)間。
            如果使用select處理多個(gè)套接字,那么需要使用一個(gè)數(shù)組(也可以是其他結(jié)構(gòu))來(lái)記錄各個(gè)描述符的狀態(tài)。而使用poll則不需要,下面看poll函數(shù)。

            (二)poll()函數(shù)

            原型如下:

            1 int poll(struct pollfd *fdarray, unsigned long nfds, int timeout);

            各參數(shù)含義如下:
            • struct pollfd *fdarray:一個(gè)結(jié)構(gòu)體,用來(lái)保存各個(gè)描述符的相關(guān)狀態(tài)。
            • unsigned long nfds:fdarray數(shù)組的大小,即里面包含有效成員的數(shù)量。
            • int timeout:設(shè)定的超時(shí)時(shí)間。(以毫秒為單位)
            poll函數(shù)返回值及含義如下:
            • -1:有錯(cuò)誤產(chǎn)生
            • 0:超時(shí)時(shí)間到,而且沒(méi)有描述符有狀態(tài)變化
            • >0:有狀態(tài)變化的描述符個(gè)數(shù)
            著重講fdarray數(shù)組,因?yàn)檫@是它和select()函數(shù)主要的不同的地方:
            pollfd的結(jié)構(gòu)如下:

            1 struct pollfd {
            2    int fd;                  /* descriptor to check */
            3    short events;      /* events of interest on fd */
            4    short revents;     /* events that occured on fd */
            5 };

            其實(shí)poll()和select()函數(shù)要處理的問(wèn)題是相同的,只不過(guò)是不同組織在幾乎相同時(shí)刻同時(shí)推出的,因此才同時(shí)保留了下來(lái)。select()函數(shù)把可讀描述符、可寫(xiě)描述符、錯(cuò)誤描述符分在了三個(gè)集合里,這三個(gè)集合都是用bit位來(lái)標(biāo)記一個(gè)描述符,一旦有若干個(gè)描述符狀態(tài)發(fā)生變化,那么它將被置位,而其他沒(méi)有發(fā)生變化的描述符的bit位將被clear,也就是說(shuō)select()的readset、writeset、errorset是一個(gè)value-result類型,通過(guò)它們傳值,而也通過(guò)它們返回結(jié)果。這樣的一個(gè)壞處是每次重新select 的時(shí)候?qū)媳仨氈匦沦x值。而poll()函數(shù)則與select()采用的方式不同,它通過(guò)一個(gè)結(jié)構(gòu)數(shù)組保存各個(gè)描述符的狀態(tài),每個(gè)結(jié)構(gòu)體第一項(xiàng)fd代表描述符,第二項(xiàng)代表要監(jiān)聽(tīng)的事件,也就是感興趣的事件,而第三項(xiàng)代表poll()返回時(shí)描述符的返回狀態(tài)。合法狀態(tài)如下:

            • POLLIN:                有普通數(shù)據(jù)或者優(yōu)先數(shù)據(jù)可讀
            • POLLRDNORM:    有普通數(shù)據(jù)可讀
            • POLLRDBAND:    有優(yōu)先數(shù)據(jù)可讀
            • POLLPRI:              有緊急數(shù)據(jù)可讀
            • POLLOUT:            有普通數(shù)據(jù)可寫(xiě)
            • POLLWRNORM:   有普通數(shù)據(jù)可寫(xiě)
            • POLLWRBAND:    有緊急數(shù)據(jù)可寫(xiě)
            • POLLERR:            有錯(cuò)誤發(fā)生
            • POLLHUP:            有描述符掛起事件發(fā)生
            • POLLNVAL:          描述符非法

            對(duì)于POLLIN | POLLPRI等價(jià)與select()的可讀事件;POLLOUT | POLLWRBAND等價(jià)與select()的可寫(xiě)事件;POLLIN 等價(jià)與POLLRDNORM | POLLRDBAND,而POLLOUT等價(jià)于POLLWRBAND。如果你對(duì)一個(gè)描述符的可讀事件和可寫(xiě)事件以及錯(cuò)誤等事件均感興趣那么你應(yīng)該都進(jìn)行相應(yīng)的設(shè)置。
            對(duì)于timeout的設(shè)置如下:
            • INFTIM:   wait forever
            • 0:            return immediately, do not block
            • >0:         wait specified number of milliseconds

            對(duì)于select()和poll()函數(shù)的講解暫時(shí)到此。 更多細(xì)節(jié)請(qǐng)參考下面這篇博文:http://www.shnenglu.com/just51living/archive/2011/07/28/151995.html
            posted on 2011-10-26 19:04 myjfm 閱讀(12007) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程
            97精品伊人久久大香线蕉app| 久久综合伊人77777| 久久这里只精品99re66| 成人a毛片久久免费播放| 国产精品久久久久久一区二区三区| 亚洲国产精品无码成人片久久| 久久综合九色综合网站| 久久久久人妻一区二区三区| 中文字幕久久精品| 久久久久国产精品人妻| 久久精品国产亚洲AV嫖农村妇女| 亚洲va久久久噜噜噜久久天堂| 国产A三级久久精品| 久久人人妻人人爽人人爽| 国内精品久久久久久99| 亚洲天堂久久精品| 性高朝久久久久久久久久| 99精品国产免费久久久久久下载| 久久精品国产亚洲AV久| 久久久久人妻一区二区三区vr| 久久99免费视频| 伊人精品久久久久7777| 久久精品中文无码资源站| 久久水蜜桃亚洲av无码精品麻豆 | 人人狠狠综合久久亚洲| 久久99热这里只频精品6| 久久久久亚洲AV片无码下载蜜桃| 久久精品国产半推半就| 97视频久久久| 国产一区二区三区久久精品| 久久久久免费视频| 久久人人爽人人爽人人片AV不| 久久福利青草精品资源站| 久久亚洲精品国产亚洲老地址 | 99精品久久久久久久婷婷| 亚洲国产精品一区二区三区久久| 亚洲精品无码久久一线| 久久se这里只有精品| 久久综合狠狠综合久久| 伊人久久大香线蕉无码麻豆| 久久精品a亚洲国产v高清不卡|