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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

select、poll、epoll 比较

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

轉載:http://blog.csdn.net/dodo_328/article/details/39081183

1.Selet:本質上是通過設置或者檢查存放fd標志位的數據結構來進行下一步處理。

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

????????????????????????? 2 需要維護一個用來存放大量fd的數據結構,這樣會使得用戶空間和內核空間在傳遞該結構時復制開銷大;

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

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

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

參數:nfds 需要監聽的最大fd 值加1;

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

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

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

?????????? timeout? 超過此時間后函數返回。

返回值:-1? 發生錯誤;

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

?????????????num?? 滿足需求的文件描述符數目。

?

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

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

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

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

程序實例:

[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:它將用戶傳入的數組拷貝到內核空間,然后查閱每個fd對應的設備狀態,如果設備就緒則在設備等待隊列中加入一項并繼續遍歷,如果遍歷完所有的fd沒有發現設備就緒,則掛起當前進程,直到設備就緒或者主動超時,被喚醒后,它又要再次遍歷fd,這個過程經歷了多次無謂的遍歷。

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

    ????????? 缺點:大量的fd數組被整體復制于用戶態和內核地址空間之間。

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

    struct pollfd{

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

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

    ?????? short? revents; //實際發生的事件

    }

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

    參數:fds[]? 文件描述符以及等待的事件結構數組;

    ?????????? nfds? 表示監聽的fds的長度;

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

    返回值:-1 發生錯誤;

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

    ???????????? num 滿足需求的文件描述符總數。

    events/revents:POLLIN|POLLOUT

    程序實例:

    [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. 不限制監聽的描述符個數,只受進程打開的描述符總數的限制;

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

    ????????????3.使用共享內存的方式,不在用戶和內核之間反復傳遞監聽的描述信息;

    ??????????? 4.返回參數就是觸發事件的列表,不再遍歷。

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

    ?????????????????????? 2.支持水平和邊緣觸發。

    int epoll_creat(int size)

    功能:用來創建epoll文件描述符。

    參數:size 能在epoll上關注的最大fd數。

    返回值:epfd。

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

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

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

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

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

    ?????????? event? 與fd 相關聯的監聽事件。

    struct? epoll_event{

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

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

    };

    events:EPOLLIN 可讀。

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

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

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

    ??????????? EPOLLPRI 緊急數據可讀。

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

    ??????????? EPOLLHUP 掛起。 EPOLLERR 和EPOLLHUP始終由epoll_wait監聽,不需要用戶設置。

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

    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)

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

    ?????????? events? 用于回傳待處理事件的數組,值結果參數。

    ?????????? maxevents? 每次能處理的事件數。

    ?????????? timeout? 超時設置。

    返回值:-1? 發生錯誤;

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

    ???????????? num? 觸發事件的描述符總數。

    程序實例:

    [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);??
  • }??


  • 總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。