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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

select、poll、epoll 比较

發(fā)布時間:2023/11/30 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 select、poll、epoll 比较 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

1.Selet:本質(zhì)上是通過設(shè)置或者檢查存放fd標志位的數(shù)據(jù)結(jié)構(gòu)來進行下一步處理。

?????????????? 缺點:1 單個進程可監(jiān)視的fd數(shù)量被限制,因為受描述符集合fd_set限制,fd數(shù)量最大不超過1024;

????????????????????????? 2 需要維護一個用來存放大量fd的數(shù)據(jù)結(jié)構(gòu),這樣會使得用戶空間和內(nèi)核空間在傳遞該結(jié)構(gòu)時復(fù)制開銷大;

????????????????????????? 3 對socket進行掃描時是線性掃描;

????????????????????????? 4 Linux的實現(xiàn)中select返回時會將timeout修改為剩余時間,所以重復(fù)利用timeout需要注意。

函數(shù)原型:int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);

參數(shù):nfds 需要監(jiān)聽的最大fd 值加1;

???????????readfds 等待從此集合中的文件描述符中到來的數(shù)據(jù);

?????????? writefds 等待向此集合中的文件描述符寫入的數(shù)據(jù);

?????????? exceptfds 等待這些文件描述符操作的異常;

?????????? timeout? 超過此時間后函數(shù)返回。

返回值:-1? 發(fā)生錯誤;

????????????? 0??? 超時;

?????????????num?? 滿足需求的文件描述符數(shù)目。

?

void FD_CLR(int fd,fd_set *set):用來從文件描述符集合中刪除一個文件描述符。

void FD_ISSET(int fd, fd_set *set):用來測試在這個文件描述符集合中,此文件描述符是否被觸發(fā)。

void FD_SET(int fd, fd_set *set):用來將一個文件描述符設(shè)置到文件描述符集合中去。

void FD_ZERO(fd_set *set):用來將文件描述符集合清零。

程序?qū)嵗?#xff1a;

[objc]?view plain?copy
  • #include<stdio.h>??
  • #include<stdlib.h>??
  • #include<sys/time.h>??
  • #include<sys/types.h>??
  • #include<unistd.h>??
  • #include<fcntl.h>??
  • ??
  • #define?oops(m,x){perror(m);exit(x);}??
  • void?showdata(charchar?*,int?);??
  • ??
  • int?main(int?ac,charchar?*av[])??
  • {??
  • ????int?fd1,fd2;??
  • ????int?max_fd;??
  • ????fd_set?readfds;??
  • ????struct?timeval?timeout;??
  • ????int?retval;??
  • ??????
  • ????if(ac?!=?4)??
  • ????{??
  • ????????fprintf(stderr,"Usage:%s?file1?file2?timeout\n",*av);??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????if((fd1?=?open(av[1],O_RDONLY))?==?-1)??
  • ????????oops("file1?open",2);??
  • ??
  • ????if((fd2?=?open(av[2],O_RDONLY))?==?-1)??
  • ????????oops("file2?open",3);??
  • ??
  • ????max_fd?=?1?+?((fd1?>?fd2)?fd1:fd2);??
  • ??
  • ????while(1)??
  • ????{??
  • ????????FD_ZERO(&readfds);??
  • ????????FD_SET(fd1,&readfds);??
  • ????????FD_SET(fd2,&readfds);??
  • ??
  • ????????timeout.tv_sec?=?atoi(av[3]);??
  • ????????timeout.tv_usec?=?0;??
  • ??
  • ????????retval?=?select(max_fd,&readfds,NULL,NULL,&timeout);??
  • ??
  • ????????if(retval?==?-1)??
  • ????????????oops("select",4);??
  • ????????if(retval?>?0)??
  • ????????{??
  • ????????????if(FD_ISSET(fd1,&readfds))??
  • ????????????????showdata(av[1],fd1);??
  • ????????????if(FD_ISSET(fd2,&readfds))??
  • ????????????????showdata(av[2],fd2);??
  • ????????}??
  • ????????else??
  • ????????????printf("no?input?after?%d?seconds\n",atoi(av[3]));??
  • ????}??
  • }??
  • ??
  • void?showdata(charchar?*fname,int?fd)??
  • {??
  • ????char?buf[BUFSIZ];??
  • ????int?n;??
  • ??
  • ????printf("%s:",fname);??
  • ????fflush(stdout);??
  • ????n?=?read(fd,buf,BUFSIZ);??
  • ????if(n?==?-1)??
  • ????????oops(fname,5);??
  • ????write(1,buf,n);??
  • ????write(1,"\n",1);??
  • }??

  • ?

    2.Poll:它將用戶傳入的數(shù)組拷貝到內(nèi)核空間,然后查閱每個fd對應(yīng)的設(shè)備狀態(tài),如果設(shè)備就緒則在設(shè)備等待隊列中加入一項并繼續(xù)遍歷,如果遍歷完所有的fd沒有發(fā)現(xiàn)設(shè)備就緒,則掛起當前進程,直到設(shè)備就緒或者主動超時,被喚醒后,它又要再次遍歷fd,這個過程經(jīng)歷了多次無謂的遍歷。

    ????????? 優(yōu)點:沒有最大鏈接數(shù)的限制,原因是因為它是基于鏈表來存儲的;不會修改timeout的值。

    ????????? 缺點:大量的fd數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核地址空間之間。

    ????????? 特點:“水平觸發(fā)”:如果報告fd后,沒有被處理,那么下次poll時會再次報告該fd。

    struct pollfd{

    ?????? int fd;? //文件描述符

    ???????short events;? //等待的事件

    ?????? short? revents; //實際發(fā)生的事件

    }

    函數(shù)原型:int poll(struct pollfd? fds[ ], nfds_t nfds,int timeout);

    參數(shù):fds[]? 文件描述符以及等待的事件結(jié)構(gòu)數(shù)組;

    ?????????? nfds? 表示監(jiān)聽的fds的長度;

    ???????????timeout 超時;

    返回值:-1 發(fā)生錯誤;

    ????????????? 0?? 超時;

    ???????????? num 滿足需求的文件描述符總數(shù)。

    events/revents:POLLIN|POLLOUT

    程序?qū)嵗?#xff1a;

    [objc]?view plain?copy
  • #include<stdio.h>??
  • #include<stdlib.h>??
  • #include<unistd.h>??
  • #include<poll.h>??
  • #include<fcntl.h>??
  • ??
  • #define?oops(m,x){perror(m);exit(x);}??
  • ??
  • void?showdata(charchar?*,int);???
  • ??
  • int?main(int?ac,charchar?*av[])??
  • {??
  • ????int?timeout,fd1,fd2;??
  • ????struct?pollfd?poll_array[2];??
  • ????//int?i;??
  • ????int?ret;??
  • ??
  • ????if(ac?!=?4)??
  • ????{??
  • ????????fprintf(stderr,"Usage:%s?file1?file2?timeout\n",*av);??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????timeout?=?atoi(av[3]);??
  • ??
  • ????if((fd1?=?open(av[1],O_RDONLY))?==?-1)??
  • ????????oops(av[1],2);??
  • ????if((fd2?=?open(av[2],O_RDONLY))?==?-1)??
  • ????????oops(av[2],3);??
  • ??
  • ????poll_array[0].fd?=?fd1;??
  • ????poll_array[0].events?=?POLLIN;??
  • ????poll_array[1].fd?=?fd2;??
  • ????poll_array[1].events?=?POLLIN;??
  • ??
  • ????while(1)??
  • ????{??
  • ????????ret?=?poll(poll_array,2,timeout);??
  • ??
  • ????????if(ret?==?-1)??
  • ????????????oops("poll?error\n",1);??
  • ????????if(ret?==?0)??
  • ????????{??
  • ????????????printf("timeout..\n");??
  • ????????????continue;??
  • ????????}??
  • ??
  • ????????if(poll_array[0].revents?&?POLLIN)??
  • ????????{??
  • ????????????showdata(av[1],fd1);??
  • ????????}??
  • ??
  • ????????if(poll_array[1].revents?&POLLIN)??
  • ????????????showdata(av[2],fd2);??
  • ????}??
  • ????return?0;??
  • }??
  • ??
  • void?showdata(charchar?*fname,int?fd)??
  • {??
  • ????char?buf[BUFSIZ];??
  • ????int?n;??
  • ??
  • ????printf("%s:",fname);??
  • ????fflush(stdout);??
  • ????n?=?read(fd,buf,BUFSIZ);??
  • ????printf("n:%d\n",n);??
  • ????if(n?==?-1)??
  • ????????oops(fname,4);??
  • ????write(1,buf,n);??
  • ????write(1,"\n",1);??
  • }??

  • ?

    3.Epoll:解決了select和poll的幾個性能上的缺陷

    ????????????1. 不限制監(jiān)聽的描述符個數(shù),只受進程打開的描述符總數(shù)的限制;

    ????????????2. 監(jiān)聽性能不隨著監(jiān)聽描述符數(shù)的增加而增加,是0(1)的,不再是輪詢描述符來探測事件,而是描述符主動上報事件;

    ????????????3.使用共享內(nèi)存的方式,不在用戶和內(nèi)核之間反復(fù)傳遞監(jiān)聽的描述信息;

    ??????????? 4.返回參數(shù)就是觸發(fā)事件的列表,不再遍歷。

    ??????????? 注意:1.epoll創(chuàng)建了描述符,最后要close(epfd);

    ?????????????????????? 2.支持水平和邊緣觸發(fā)。

    int epoll_creat(int size)

    功能:用來創(chuàng)建epoll文件描述符。

    參數(shù):size 能在epoll上關(guān)注的最大fd數(shù)。

    返回值:epfd。

    int epoll_ctl(int epfd,int op,int fd, struct epoll_event *event)

    功能:控制對指定的文件描述符執(zhí)行op操作。

    參數(shù):epfd? epoll_creat()函數(shù)的返回值。

    ?????????? op? EPOLL_CTL_ADD(增加)/EPOLL_CTL_DEL(刪除)/EPOLL_CTL_MOD(修改)。

    ???????????fd?? 文件描述符。

    ?????????? event? 與fd 相關(guān)聯(lián)的監(jiān)聽事件。

    struct? epoll_event{

    ???????????_uint32_t? events;

    ?????????? epoll_data_t? data;

    };

    events:EPOLLIN 可讀。

    ??????????? EPOLLOUT 可寫。

    ??????????? EPOLLRDHUP 套接口對端close或shutdown寫,在ET(邊緣)模式下比較有用。

    ??????????? EPOLLET 邊緣觸發(fā)模式,在描述符狀態(tài)跳變時才上報監(jiān)聽事件(監(jiān)聽默認是LT(水平)模式)。

    ??????????? EPOLLPRI 緊急數(shù)據(jù)可讀。

    ??????????? EPOLLERR 異常事件。

    ??????????? EPOLLHUP 掛起。 EPOLLERR 和EPOLLHUP始終由epoll_wait監(jiān)聽,不需要用戶設(shè)置。

    ??????????? EPOLLONESHOT? 只一次有效,描述符在觸發(fā)一次事件之后自動失效。fd還在繼續(xù)監(jiān)聽,直到使用EPOLL_CTL_MOD重新激活,設(shè)置新的監(jiān)聽事件。

    data: 是個共用體,可以存放和fd綁定的描述符信息。比如ip/port等。

    typedef? union? epoll_data{

    ????????? void *ptr;//存放與fd綁定的信息。

    ??????????int fd;

    ????????? _uint32_t? u32;

    ????????? _uint32_t? u64;

    }epoll_data_t;

    int epoll_wait(int epfd,struct epoll_event *events,int maxevents, int timeout)

    參數(shù):epfd? epoll_creat()的返回值.

    ?????????? events? 用于回傳待處理事件的數(shù)組,值結(jié)果參數(shù)。

    ?????????? maxevents? 每次能處理的事件數(shù)。

    ?????????? timeout? 超時設(shè)置。

    返回值:-1? 發(fā)生錯誤;

    ????????????? 0?? 超時;

    ???????????? num? 觸發(fā)事件的描述符總數(shù)。

    程序?qū)嵗?#xff1a;

    [objc]?view plain?copy
  • #include<stdio.h>??
  • #include<stdlib.h>??
  • #include<poll.h>??
  • #include<unistd.h>??
  • #include<fcntl.h>??
  • #include<sys/types.h>??
  • #include<sys/epoll.h>??
  • ??
  • #define?oops(m,x){perror(m);exit(x);}??
  • #define?MAX_SIZE_EVENT??500??
  • ??
  • void?showdata(int?,charchar?*);??
  • ??
  • int?main(int?ac?,charchar?*av[])??
  • {??
  • ????int?fd1,fd2;??
  • ????int?time;??
  • ????int?epfd;??
  • ????struct?epoll_event?eventList[MAX_SIZE_EVENT];??
  • ????struct?epoll_event?fd1_event;??
  • ????struct?epoll_event?fd2_event;??
  • ????int?ret;??
  • ????int?n?;??
  • ??????
  • ????if(ac?!=?4)??
  • ????{??
  • ????????fprintf(stderr,"Usage:%s?file1?file2?timeout\n",*av);??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????if((fd1?=?open(av[1],O_RDONLY))?==?-1)??
  • ????????oops("file1?open",2);??
  • ????if((fd2?=?open(av[2],O_RDONLY))?==?-1)??
  • ????????oops("file2?open",3);??
  • ??????
  • ????time?=?atoi(av[3]);??
  • ??
  • ????epfd?=?epoll_create(MAX_SIZE_EVENT);??
  • ????fd1_event.events?=?EPOLLIN|EPOLLET;??
  • ????fd1_event.data.fd?=?fd1;??
  • ????fd1_event.data.ptr?=?av[1];??
  • ????fd2_event.events?=?EPOLLIN|EPOLLET;??
  • ????fd2_event.data.fd?=?fd2;??
  • ????fd2_event.data.ptr?=?av[2];??
  • ??
  • ????if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd1,&fd1_event)?<?0)??
  • ????????oops("fd1_event?epoll?addfail",4);??
  • ????if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd2,&fd2_event)?<?0)??
  • ????????oops("fd2_event?epoll?addfail",5);??
  • ??
  • ????while(1)??
  • ????{??
  • ????????ret?=?epoll_wait(epfd,eventList,MAX_SIZE_EVENT,time);??
  • ????????if(ret?<?0)??
  • ????????????oops("epoll?error",6);??
  • ????????if(ret?==?0)??
  • ????????{??
  • ????????????printf("timeout\n");??
  • ????????}??
  • ??
  • ????????for(n?=?0;n?<?ret;?n++)??
  • ????????{??
  • ????????????if(eventList[n].events?&?EPOLLERR?||?eventList[n].events?&?EPOLLHUP?||?!(eventList[n].events?&?EPOLLIN))??
  • ????????????{??
  • ????????????????printf("epoll?error");??
  • ????????????????close(epfd);??
  • ????????????????close(eventList[n].data.fd);??
  • ????????????????return?-1;??
  • ????????????}??
  • ????????????else?if(eventList[n].events?&?EPOLLIN)??
  • ????????????????showdata(eventList[n].data.fd,eventList[n].data.ptr);??
  • ????????}??
  • ??
  • ????}??
  • ????close(epfd);??
  • ????close(fd1);??
  • ????close(fd2);??
  • ????return?0;??
  • }??
  • ??
  • void?showdata(int?fd,charchar?*fname)??
  • {??
  • ????char?buf[BUFSIZ];??
  • ????int?n;??
  • ??
  • ????printf("%s:",fname);??
  • ????fflush(stdout);??
  • ??
  • ????n?=?read(fd,buf,BUFSIZ);??
  • ????if(n?==?-1)??
  • ????????oops("fd?read",6);??
  • ????write(1,buf,n);??
  • ????write(1,"\n",1);??
  • }??


  • 總結(jié)

    以上是生活随笔為你收集整理的select、poll、epoll 比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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