电竞比分网-中国电竞赛事及体育赛事平台

分享

Linux poll實(shí)例

 WUCANADA 2012-08-21
poll()函數(shù):這個(gè)函數(shù)是某些Unix系統(tǒng)提供的用于執(zhí)行與select()函數(shù)同等功能的函數(shù),下面是這個(gè)函數(shù)的聲明:

#include <poll.h>

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

參數(shù)說(shuō)明:

fds:是一個(gè)struct pollfd結(jié)構(gòu)類(lèi)型的數(shù)組,用于存放需要檢測(cè)其狀態(tài)的Socket描述符;每當(dāng)調(diào)用這個(gè)函數(shù)之后,系統(tǒng)不會(huì)清空這個(gè)數(shù)組,操作起來(lái)比較方便;特別是對(duì)于 socket連接比較多的情況下,在一定程度上可以提高處理的效率;這一點(diǎn)與select()函數(shù)不同,調(diào)用select()函數(shù)之后,select() 函數(shù)會(huì)清空它所檢測(cè)的socket描述符集合,導(dǎo)致每次調(diào)用select()之前都必須把socket描述符重新加入到待檢測(cè)的集合中;因 此,select()函數(shù)適合于只檢測(cè)一個(gè)socket描述符的情況,而poll()函數(shù)適合于大量socket描述符的情況;

nfds:nfds_t類(lèi)型的參數(shù),用于標(biāo)記數(shù)組fds中的結(jié)構(gòu)體元素的總數(shù)量;

timeout:是poll函數(shù)調(diào)用阻塞的時(shí)間,單位:毫秒;

返回值:

>0:數(shù)組fds中準(zhǔn)備好讀、寫(xiě)或出錯(cuò)狀態(tài)的那些socket描述符的總數(shù)量;

==0:數(shù)組fds中沒(méi)有任何socket描述符準(zhǔn)備好讀、寫(xiě),或出錯(cuò);此時(shí)poll超時(shí),超時(shí)時(shí)間是timeout毫秒;換句話(huà)說(shuō),如果所檢測(cè)的 socket描述符上沒(méi)有任何事件發(fā)生的話(huà),那么poll()函數(shù)會(huì)阻塞timeout所指定的毫秒時(shí)間長(zhǎng)度之后返回,如果timeout==0,那么 poll() 函數(shù)立即返回而不阻塞,如果timeout==INFTIM,那么poll() 函數(shù)會(huì)一直阻塞下去,直到所檢測(cè)的socket描述符上的感興趣的事件發(fā)生是才返回,如果感興趣的事件永遠(yuǎn)不發(fā)生,那么poll()就會(huì)永遠(yuǎn)阻塞下去;
 A timeout of INFTIM means** wait indefinitely.
-1:  poll函數(shù)調(diào)用失敗,同時(shí)會(huì)自動(dòng)設(shè)置全局變量errno;

如果待檢測(cè)的socket描述符為負(fù)值,則對(duì)這個(gè)描述符的檢測(cè)就會(huì)被忽略,也就是不會(huì)對(duì)成員變量events進(jìn)行檢測(cè),在events上注冊(cè)的事件也會(huì)被 忽略,poll()函數(shù)返回的時(shí)候,會(huì)把成員變量revents設(shè)置為0,表示沒(méi)有事件發(fā)生;

另外,poll() 函數(shù)不會(huì)受到socket描述符上的O_NDELAY標(biāo)記和O_NONBLOCK標(biāo)記的影響和制約,也就是說(shuō),不管socket是阻塞的還是非阻塞 的,poll()函數(shù)都不會(huì)收到影響;而select()函數(shù)則不同,select()函數(shù)會(huì)受到O_NDELAY標(biāo)記和O_NONBLOCK標(biāo)記的影 響,如果socket是阻塞的socket,則調(diào)用select()跟不調(diào)用select()時(shí)的效果是一樣的,socket仍然是阻塞式TCP通訊,相 反,如果socket是非阻塞的socket,那么調(diào)用select()時(shí)就可以實(shí)現(xiàn)非阻塞式TCP通訊;

所以poll() 函數(shù)的功能和返回值的含義與 select() 函數(shù)的功能和返回值的含義是完全一樣的,兩者之間的差別就是內(nèi)部實(shí)現(xiàn)方式不一樣,select()函數(shù)基本上可以在所有支持文件描述符操作的系統(tǒng)平臺(tái)上運(yùn) 行(如:Linux 、Unix 、Windows、MacOS等),可移植性好,而poll()函數(shù)則只有個(gè)別的的操作系統(tǒng)提供支持(如:SunOS、Solaris、AIX、HP提供 支持,但是Linux不提供支持),可移植性差;

strust pollfd結(jié)構(gòu)說(shuō)明:

typedef struct pollfd {
        int fd;                               /* 需要被檢測(cè)或選擇的文件描述符*/
        short events;                   /* 對(duì)文件描述符fd上感興趣的事件 */
        short revents;                  /* 文件描述符fd上當(dāng)前實(shí)際發(fā)生的事件*/
} pollfd_t;

typedef unsigned long   nfds_t;

經(jīng)常檢測(cè)的事件標(biāo)記: POLLIN/POLLRDNORM(可讀)、POLLOUT/POLLWRNORM(可寫(xiě))、POLLERR(出錯(cuò))

如果是對(duì)一個(gè)描述符上的多個(gè)事件感興趣的話(huà),可以把這些常量標(biāo)記之間進(jìn)行按位或運(yùn)算就可以了;

比如:對(duì)socket描述符fd上的讀、寫(xiě)、異常事件感興趣,就可以這樣做:struct pollfd  fds;

fds[nIndex].events=POLLIN | POLLOUT | POLLERR;

當(dāng) poll()函數(shù)返回時(shí),要判斷所檢測(cè)的socket描述符上發(fā)生的事件,可以這樣做: struct pollfd  fds;

檢測(cè)可讀TCP連接請(qǐng)求:

if((fds[nIndex].revents & POLLIN) == POLLIN){//接收數(shù)據(jù)/調(diào)用accept()接收連接請(qǐng)求}

檢測(cè)可寫(xiě):

if((fds[nIndex].revents & POLLOUT) == POLLOUT){//發(fā)送數(shù)據(jù)}

檢測(cè)異常:

if((fds[nIndex].revents & POLLERR) == POLLERR){//異常處理}

poll函數(shù)可用的測(cè)試值

常量 說(shuō)明
POLLIN 普通或優(yōu)先級(jí)帶數(shù)據(jù)可讀
POLLRDNORM 普通數(shù)據(jù)可讀
POLLRDBAND 優(yōu)先級(jí)帶數(shù)據(jù)可讀
POLLPRI 高優(yōu)先級(jí)數(shù)據(jù)可讀
POLLOUT 普通數(shù)據(jù)可寫(xiě)
POLLWRNORM 普通數(shù)據(jù)可寫(xiě)
POLLWRBAND 優(yōu)先級(jí)帶數(shù)據(jù)可寫(xiě)
POLLERR 發(fā)生錯(cuò)誤
POLLHUP 發(fā)生掛起
POLLNVAL 描述字不是一個(gè)打開(kāi)的文件

  注意:后三個(gè)只能作為描述字的返回結(jié)果存 儲(chǔ)在revents中,而不能作為測(cè)試條件用于events中。

  第二個(gè)參數(shù)nfds是用來(lái)指定數(shù)組fdarray的長(zhǎng)度。

  最后一個(gè)參數(shù)timeout是指定poll函數(shù)返回前等待多長(zhǎng)時(shí)間。 它的取值如下:

timeout值 說(shuō)明
INFTIM 永遠(yuǎn)等待
0 立即返回,不阻塞進(jìn)程
>0 等待指定數(shù)目的毫秒數(shù)

  一個(gè)使用poll的網(wǎng)絡(luò)程序例子:


文章出處:飛諾網(wǎng)(www.):http://dev./course/6_s ... 0100326/201427.html

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <poll.h>

#define MAX_BUFFER_SIZE   1024    /* 緩沖區(qū)大小*/
#define IN_FILES   3    /* 多路復(fù)用輸入文件數(shù)目*/
#define TIME_DELAY   6000    /* 超時(shí)時(shí)間秒數(shù) */
#define MAX(a, b)   ((a > b)?(a)b))

int main(void)
{
struct pollfd fds[IN_FILES];
char buf[MAX_BUFFER_SIZE];
int i, res, real_read, maxfd;

/*首先按一定的權(quán)限打開(kāi)兩個(gè)源文件*/
fds[0].fd = 0;
if((fds[1].fd = open ("in1", O_RDONLY|O_NONBLOCK)) < 0)
{
   printf("Open in1 error\n";
   return 1;
}
      
   if((fds[2].fd = open ("in2", O_RDONLY|O_NONBLOCK)) < 0)
   {
    printf("Open in2 error\n";
   return 1;
}

/*取出兩個(gè)文件描述符中的較大者*/
for (i = 0; i < IN_FILES; i++)
{
   fds.events = POLLIN;
}

while(fds[0].events || fds[1].events || fds[2].events)
{
   if (poll(fds, IN_FILES, TIME_DELAY) <= 0)
   {
    printf("oll error\n";
    return 1;
   }
  
   for (i = 0; i< IN_FILES; i++)
   {
    if (fds.revents)
    {
     memset(buf, 0, MAX_BUFFER_SIZE);
     real_read = read(fds.fd, buf, MAX_BUFFER_SIZE);

     if (real_read < 0)
     {
      if (errno != EAGAIN)
      {
       return 1;
      }
     }
     else if (!real_read)
     {
      close(fds.fd);
      fds.events = 0;
     }
     else
     {
      if (i == 0)
      {
       if ((buf[0] == 'q') || (buf[0] == 'Q'))
       {
        return 1;
       }
      }
      else
      {
       buf[real_read] = '\0';
       printf("%s", buf);
      }
     } /* end of if real_read*/
    } /* end of if revents */
   } /* end of for */
} /*end of while */
exit(0);
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多