日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

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ù)說明:

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

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

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

返回值:

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

==0:數(shù)組fds中沒有任何socket描述符準(zhǔn)備好讀、寫,或出錯(cuò);此時(shí)poll超時(shí),超時(shí)時(shí)間是timeout毫秒;換句話說,如果所檢測的 socket描述符上沒有任何事件發(fā)生的話,那么poll()函數(shù)會(huì)阻塞timeout所指定的毫秒時(shí)間長度之后返回,如果timeout==0,那么 poll() 函數(shù)立即返回而不阻塞,如果timeout==INFTIM,那么poll() 函數(shù)會(huì)一直阻塞下去,直到所檢測的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;

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

另外,poll() 函數(shù)不會(huì)受到socket描述符上的O_NDELAY標(biāo)記和O_NONBLOCK標(biāo)記的影響和制約,也就是說,不管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)平臺上運(yùn) 行(如:Linux 、Unix 、Windows、MacOS等),可移植性好,而poll()函數(shù)則只有個(gè)別的的操作系統(tǒng)提供支持(如:SunOS、Solaris、AIX、HP提供 支持,但是Linux不提供支持),可移植性差;

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

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

typedef unsigned long   nfds_t;

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

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

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

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

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

檢測可讀TCP連接請求:

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

檢測可寫:

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

檢測異常:

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

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

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

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

  第二個(gè)參數(shù)nfds是用來指定數(shù)組fdarray的長度。

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

timeout值 說明
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)限打開兩個(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è)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多