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
  1. #include<stdio.h>??
  2. #include<stdlib.h>??
  3. #include<sys/time.h>??
  4. #include<sys/types.h>??
  5. #include<unistd.h>??
  6. #include<fcntl.h>??
  7. ??
  8. #define?oops(m,x){perror(m);exit(x);}??
  9. void?showdata(charchar?*,int?);??
  10. ??
  11. int?main(int?ac,charchar?*av[])??
  12. {??
  13. ????int?fd1,fd2;??
  14. ????int?max_fd;??
  15. ????fd_set?readfds;??
  16. ????struct?timeval?timeout;??
  17. ????int?retval;??
  18. ??????
  19. ????if(ac?!=?4)??
  20. ????{??
  21. ????????fprintf(stderr,"Usage:%s?file1?file2?timeout\n",*av);??
  22. ????????exit(1);??
  23. ????}??
  24. ??
  25. ????if((fd1?=?open(av[1],O_RDONLY))?==?-1)??
  26. ????????oops("file1?open",2);??
  27. ??
  28. ????if((fd2?=?open(av[2],O_RDONLY))?==?-1)??
  29. ????????oops("file2?open",3);??
  30. ??
  31. ????max_fd?=?1?+?((fd1?>?fd2)?fd1:fd2);??
  32. ??
  33. ????while(1)??
  34. ????{??
  35. ????????FD_ZERO(&readfds);??
  36. ????????FD_SET(fd1,&readfds);??
  37. ????????FD_SET(fd2,&readfds);??
  38. ??
  39. ????????timeout.tv_sec?=?atoi(av[3]);??
  40. ????????timeout.tv_usec?=?0;??
  41. ??
  42. ????????retval?=?select(max_fd,&readfds,NULL,NULL,&timeout);??
  43. ??
  44. ????????if(retval?==?-1)??
  45. ????????????oops("select",4);??
  46. ????????if(retval?>?0)??
  47. ????????{??
  48. ????????????if(FD_ISSET(fd1,&readfds))??
  49. ????????????????showdata(av[1],fd1);??
  50. ????????????if(FD_ISSET(fd2,&readfds))??
  51. ????????????????showdata(av[2],fd2);??
  52. ????????}??
  53. ????????else??
  54. ????????????printf("no?input?after?%d?seconds\n",atoi(av[3]));??
  55. ????}??
  56. }??
  57. ??
  58. void?showdata(charchar?*fname,int?fd)??
  59. {??
  60. ????char?buf[BUFSIZ];??
  61. ????int?n;??
  62. ??
  63. ????printf("%s:",fname);??
  64. ????fflush(stdout);??
  65. ????n?=?read(fd,buf,BUFSIZ);??
  66. ????if(n?==?-1)??
  67. ????????oops(fname,5);??
  68. ????write(1,buf,n);??
  69. ????write(1,"\n",1);??
  70. }??


?

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
  1. #include<stdio.h>??
  2. #include<stdlib.h>??
  3. #include<unistd.h>??
  4. #include<poll.h>??
  5. #include<fcntl.h>??
  6. ??
  7. #define?oops(m,x){perror(m);exit(x);}??
  8. ??
  9. void?showdata(charchar?*,int);???
  10. ??
  11. int?main(int?ac,charchar?*av[])??
  12. {??
  13. ????int?timeout,fd1,fd2;??
  14. ????struct?pollfd?poll_array[2];??
  15. ????//int?i;??
  16. ????int?ret;??
  17. ??
  18. ????if(ac?!=?4)??
  19. ????{??
  20. ????????fprintf(stderr,"Usage:%s?file1?file2?timeout\n",*av);??
  21. ????????exit(1);??
  22. ????}??
  23. ??
  24. ????timeout?=?atoi(av[3]);??
  25. ??
  26. ????if((fd1?=?open(av[1],O_RDONLY))?==?-1)??
  27. ????????oops(av[1],2);??
  28. ????if((fd2?=?open(av[2],O_RDONLY))?==?-1)??
  29. ????????oops(av[2],3);??
  30. ??
  31. ????poll_array[0].fd?=?fd1;??
  32. ????poll_array[0].events?=?POLLIN;??
  33. ????poll_array[1].fd?=?fd2;??
  34. ????poll_array[1].events?=?POLLIN;??
  35. ??
  36. ????while(1)??
  37. ????{??
  38. ????????ret?=?poll(poll_array,2,timeout);??
  39. ??
  40. ????????if(ret?==?-1)??
  41. ????????????oops("poll?error\n",1);??
  42. ????????if(ret?==?0)??
  43. ????????{??
  44. ????????????printf("timeout..\n");??
  45. ????????????continue;??
  46. ????????}??
  47. ??
  48. ????????if(poll_array[0].revents?&?POLLIN)??
  49. ????????{??
  50. ????????????showdata(av[1],fd1);??
  51. ????????}??
  52. ??
  53. ????????if(poll_array[1].revents?&POLLIN)??
  54. ????????????showdata(av[2],fd2);??
  55. ????}??
  56. ????return?0;??
  57. }??
  58. ??
  59. void?showdata(charchar?*fname,int?fd)??
  60. {??
  61. ????char?buf[BUFSIZ];??
  62. ????int?n;??
  63. ??
  64. ????printf("%s:",fname);??
  65. ????fflush(stdout);??
  66. ????n?=?read(fd,buf,BUFSIZ);??
  67. ????printf("n:%d\n",n);??
  68. ????if(n?==?-1)??
  69. ????????oops(fname,4);??
  70. ????write(1,buf,n);??
  71. ????write(1,"\n",1);??
  72. }??


?

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
  1. #include<stdio.h>??
  2. #include<stdlib.h>??
  3. #include<poll.h>??
  4. #include<unistd.h>??
  5. #include<fcntl.h>??
  6. #include<sys/types.h>??
  7. #include<sys/epoll.h>??
  8. ??
  9. #define?oops(m,x){perror(m);exit(x);}??
  10. #define?MAX_SIZE_EVENT??500??
  11. ??
  12. void?showdata(int?,charchar?*);??
  13. ??
  14. int?main(int?ac?,charchar?*av[])??
  15. {??
  16. ????int?fd1,fd2;??
  17. ????int?time;??
  18. ????int?epfd;??
  19. ????struct?epoll_event?eventList[MAX_SIZE_EVENT];??
  20. ????struct?epoll_event?fd1_event;??
  21. ????struct?epoll_event?fd2_event;??
  22. ????int?ret;??
  23. ????int?n?;??
  24. ??????
  25. ????if(ac?!=?4)??
  26. ????{??
  27. ????????fprintf(stderr,"Usage:%s?file1?file2?timeout\n",*av);??
  28. ????????exit(1);??
  29. ????}??
  30. ??
  31. ????if((fd1?=?open(av[1],O_RDONLY))?==?-1)??
  32. ????????oops("file1?open",2);??
  33. ????if((fd2?=?open(av[2],O_RDONLY))?==?-1)??
  34. ????????oops("file2?open",3);??
  35. ??????
  36. ????time?=?atoi(av[3]);??
  37. ??
  38. ????epfd?=?epoll_create(MAX_SIZE_EVENT);??
  39. ????fd1_event.events?=?EPOLLIN|EPOLLET;??
  40. ????fd1_event.data.fd?=?fd1;??
  41. ????fd1_event.data.ptr?=?av[1];??
  42. ????fd2_event.events?=?EPOLLIN|EPOLLET;??
  43. ????fd2_event.data.fd?=?fd2;??
  44. ????fd2_event.data.ptr?=?av[2];??
  45. ??
  46. ????if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd1,&fd1_event)?<?0)??
  47. ????????oops("fd1_event?epoll?addfail",4);??
  48. ????if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd2,&fd2_event)?<?0)??
  49. ????????oops("fd2_event?epoll?addfail",5);??
  50. ??
  51. ????while(1)??
  52. ????{??
  53. ????????ret?=?epoll_wait(epfd,eventList,MAX_SIZE_EVENT,time);??
  54. ????????if(ret?<?0)??
  55. ????????????oops("epoll?error",6);??
  56. ????????if(ret?==?0)??
  57. ????????{??
  58. ????????????printf("timeout\n");??
  59. ????????}??
  60. ??
  61. ????????for(n?=?0;n?<?ret;?n++)??
  62. ????????{??
  63. ????????????if(eventList[n].events?&?EPOLLERR?||?eventList[n].events?&?EPOLLHUP?||?!(eventList[n].events?&?EPOLLIN))??
  64. ????????????{??
  65. ????????????????printf("epoll?error");??
  66. ????????????????close(epfd);??
  67. ????????????????close(eventList[n].data.fd);??
  68. ????????????????return?-1;??
  69. ????????????}??
  70. ????????????else?if(eventList[n].events?&?EPOLLIN)??
  71. ????????????????showdata(eventList[n].data.fd,eventList[n].data.ptr);??
  72. ????????}??
  73. ??
  74. ????}??
  75. ????close(epfd);??
  76. ????close(fd1);??
  77. ????close(fd2);??
  78. ????return?0;??
  79. }??
  80. ??
  81. void?showdata(int?fd,charchar?*fname)??
  82. {??
  83. ????char?buf[BUFSIZ];??
  84. ????int?n;??
  85. ??
  86. ????printf("%s:",fname);??
  87. ????fflush(stdout);??
  88. ??
  89. ????n?=?read(fd,buf,BUFSIZ);??
  90. ????if(n?==?-1)??
  91. ????????oops("fd?read",6);??
  92. ????write(1,buf,n);??
  93. ????write(1,"\n",1);??
  94. }??


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384294.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384294.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384294.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C庫函數 File

C庫函數常用的有&#xff1a;fopen, fclose, fread, fwrite, fgets, fputs, fscanf, fprintf, fseek, fgetc, fputc, ftell, feof, flush等&#xff0c; 當使用fopen打開一個文件時通常返回一個文件指針 FILE *fp。FILE類型是一個結構體&#xff0c;包含文件描述符&#xff08;…

Unix 網絡編程(四)- 典型TCP客服服務器程序開發實例及基本套接字API介紹

轉載&#xff1a;http://blog.csdn.net/michael_kong_nju/article/details/43457393 寫在開頭&#xff1a; 在上一節中我們學習了一些基礎的用來支持網絡編程的API&#xff0c;包括“套接字的地址結構”、“字節排序函數”等。這些API幾乎是所有的網絡編程中都會使用的一些&…

C庫函數與系統函數的關系

轉載于:https://www.cnblogs.com/lr1402585172/p/10464933.html

Unix網絡編程(六)高級I/O技術之復用技術 select

轉載&#xff1a;http://blog.csdn.net/michael_kong_nju/article/details/44887411 I/O復用技術 本文將討論網絡編程中的高級I/O復用技術&#xff0c;將從下面幾個方面進行展開&#xff1a; a. 什么是復用技術呢&#xff1f; b. 什么情況下需要使用復用技術呢&#xff1f; c. …

open、read、write、文件類型

open&#xff0c;打開一個文件、創建一個文件或判斷一個文件是否存在。 頭文件&#xff1a;<sys/types.h> <sys/stat.h> <fcntl.h> 重載函數有&#xff1a;int open(const char *pathname, int flags) int open(const char *pathname, int flags, mode_t m…

用模板寫單鏈表 尹成

轉載&#xff1a;http://blog.csdn.net/itcastcpp/article/details/39081953 為了加深對模板的理解&#xff0c;我們今天一起用模板寫一個單鏈表&#xff0c;希望通過這個例子&#xff0c;能夠幫助大家加深對模板的體會&#xff0c;具體如下&#xff1a; SList.hpp內容&#xf…

lseek、stat、access、chmod、strtol、truncate、unlink

lseek&#xff0c;可實現計算文件長度&#xff0c;以及文件擴展。 int ret lseek(fd, 0, SEEK_END); //文件長度printf("file lendth %d\n", ret); int ret lseek(fd, 2000, SEEK_END); //文件拓展2000個byte 在文件末尾偏移2000printf("return va…

inode淺談

索引節點inode&#xff1a;保存的其實是實際的數據的一些信息&#xff0c;這些信息稱為“元數據”(也就是對文件屬性的描述)。例如&#xff1a;文件大小&#xff0c;設備標識符&#xff0c;用戶標識符&#xff0c;用戶組標識符&#xff0c;文件模式&#xff0c;擴展屬性&#x…

Openssl-MD5

http://blog.csdn.net/sunspider107/article/details/7395904 MD5是最常用的一個信息摘要算法&#xff0c;雖然現在慢慢被SHA1算法替代&#xff0c;但還是應用廣泛。 MD5的計算結果是16個字節。 int MD5_Init(MD5_CTX *c); 初始化MD5 Context參數&#xff1b; c: MD5 context; …

opendir、readdir以及使用

opendir&#xff0c;打開一個目錄。 函數原型&#xff1a;DIR *opendir(const char *name) DIR *fopendir(int fd) DIR是一個結構指針&#xff0c;是一個內部結構&#xff0c;保存所打開的目錄信息。函數出錯返回NULL readdir&#xff0c;讀目錄 ,<dirent.h> 函數原型&am…

Linux下C語言使用openssl庫進行MD5校驗

http://blog.csdn.net/cassie_huang/article/details/53212933 作者&#xff1a;無腦仔的小明 出處&#xff1a;http://www.cnblogs.com/wunaozai/ 我們以一個字符串為例&#xff0c;新建一個文件filename.txt&#xff0c;在文件內寫入hello &#xff0c;然后在Linux下可以使…

dup、dup2、fcntl

dup、dup2&#xff0c;復制文件描述符 int dup(int oldfd);  //返回文件描述表中沒有被占用的最小可用的描述符&#xff0c;新舊描述符作用相同 int dup2(int oldfd, int newfd);  //如果new已經被打開&#xff0c;先關閉再拷貝就會指向同一個文件&#xff0c;如果old和new…

進程

創建子進程&#xff1a;fork調用&#xff0c; 一次fork調用返回兩個值&#xff0c;1、返回子進程的pid&#xff08;非負整數&#xff09; 2、返回0 父進程的fork返回子進程的id&#xff0c;子進程的fork返回0&#xff08;表示執行成功&#xff09; 創建單個子進程&#xff1a; …

Ubuntu在vmware虛擬機無法上網的解決方法

http://blog.csdn.net/xueyushenzhou/article/details/50460183 在vmware中安裝Ubuntu之后&#xff0c;我們希望基本的功能如上網、傳輸文件等功能都是可用的&#xff0c;但是經常遇到不能上網的情況。使用筆記本時&#xff0c;我們經常希望能通過無線網卡上網&#xff0c;但是…

exec函數族

fork創建子進程后執行的是和父進程相同的程序&#xff08;但有可能執行不同的代碼分支&#xff09;&#xff0c;子進程往往要調用一種exec函數以執行另一個程序。當進程調用一種exec函數時&#xff0c;該進程的用戶空間代碼和數據完全被新程序替換&#xff0c;從新程序的啟動例…

IO 多路復用之poll總結

http://www.cnblogs.com/Anker/p/3261006.html IO多路復用之poll總結 1、基本知識 poll的機制與select類似&#xff0c;與select在本質上沒有多大差別&#xff0c;管理多個描述符也是進行輪詢&#xff0c;根據描述符的狀態進行處理&#xff0c;但是poll沒有最大文件描述符數量的…

wait、waitpid

父進程調用wait函數可以回收子進程的終止信息&#xff0c;該函數有三個功能&#xff1a;&#xff08;一次wait調用回收一個子進程 回收多個用循環&#xff09; 1、阻塞等待子進程退出 2、回收子進程殘留資源 3、獲取子進程結束狀態&#xff08;退出原因&#xff09; pid_t wait…

C++項目中的extern C {}

http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html 引言 在用C的項目源碼中&#xff0c;經常會不可避免的會看到下面的代碼&#xff1a; 123456789#ifdef __cplusplusextern "C" {#endif/*...*/#ifdef __cplusplus}#endif它到底有什么用呢&#xff0c;…

管道

管道&#xff0c;其本質是一個偽文件&#xff08;實為內核緩沖區&#xff09;&#xff1b;由兩個文件描述符引用&#xff0c;一個表示讀端、一個表示寫端&#xff1b;規定數據從管道的寫端流入&#xff0c;讀端流出。 管道的原理&#xff1a;管道實為內核使用環形隊列機制&…

C/S、B/S的區別

C/S結構&#xff0c;即Client/Server(客戶機/服務器)結構&#xff0c;是大家熟知的軟件系統體系結構&#xff0c;通過將任務合理分配到Client端和Server端&#xff0c;降低了系統的通訊開銷&#xff0c;可以充分利用兩端硬件環境的優勢。早期的軟件系統多以此作為首選設計標準。…