Linux epoll服务器、epoll、poll、select优缺点
2017-06-29 17:40
369 查看
epoll、poll和select优缺点
select
优点
(1)select()的可移植性更好,在某些Unix系统上不支持poll()(2)select() 对于超时值提供了更好的精度:微秒,而poll是毫秒
缺点
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024
poll
优点
(1)poll() 不要求开发者计算最大文件描述符加一的大小。(2)poll() 在应付大数目的文件描述符的时候相比于select速度更快
(3)它没有最大连接数的限制,原因是它是基于链表来存储的。
缺点
(1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。(2)与select一样,poll返回后,需要轮询pollfd来获取就绪的描述符
epoll
epoll底层实现
在调用epoll_create时操作系统会创建一颗红黑树存放socket和一个队列存放就绪事件优点
(1)支持一个进程打开大数目的socket描述符(FD)(2)IO效率不随FD数目增加而线性下降
(3)使用mmap加速内核与用户空间的消息传递。
epoll服务器实现
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #define MAX_EPOLL_EVENTS 64 static void usage(char* arg) { printf("Usage:%s [local_ip][local_port]\n",arg); } int starup(const char* ip,int port) { int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0) { perror("socket"); exit(2); } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = inet_addr(ip); int opt = 1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); if(bind(sock,(struct sockaddr*)&server,sizeof(server)) < 0) { perror("bind"); exit(3); } if(listen(sock,5) < 0) { perror("listen"); exit(4); } return sock; } int main(int argc,char* argv[]) { if(3 != argc) { usage(argv[0]); return 1; } int listen_sock = starup(argv[1],atoi(argv[2])); int epfd = epoll_create(200); if(epfd < 0) { perror("epoll_create"); return 5; } struct epoll_event ev,ev_array[MAX_EPOLL_EVENTS]; ev.events = EPOLLIN; ev.data.fd = listen_sock; if(epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev) != 0) { perror("epoll_ctl"); return 6; } while(1) { int num = epoll_wait(epfd,ev_array,MAX_EPOLL_EVENTS,10000); switch(num) { case -1: { perror("epoll_wait"); return 7; break; } case 0: { printf("nothing ready...\n"); break; } default: { int i; for(i = 0;i < num; ++i) { if(ev_array[i].data.fd == listen_sock && ev_array[i].events & EPOLLIN) { struct sockaddr_in client; socklen_t len = sizeof(client); int new_sock = accept(listen_sock,(struct sockaddr*)&client,&len); if(new_sock < 0) { perror("accept"); continue; } printf("get a new client:%s,%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); struct epoll_event event; event.events = EPOLLIN | EPOLLOUT; event.data.fd = new_sock; if(epoll_ctl(epfd,EPOLL_CTL_ADD,new_sock,&event) != 0) { perror("epoll_ctl"); close(new_sock); continue; } } else if(ev_array[i].events & E 4000 POLLIN) { char buf[1024]; ssize_t s = read(ev_array[i].data.fd,buf,sizeof(buf)-1); if(s<0) { perror("read:EPOLLIN"); if(epoll_ctl(epfd,EPOLL_CTL_DEL,ev_array[i].data.fd,&ev_array[i])!=0) { perror("epoll_ctl"); continue; } close(ev_array[i].data.fd); continue; } else if(s == 0) { printf("client quit...\n"); epoll_ctl(epfd,EPOLL_CTL_DEL,ev_array[i].data.fd,&ev_array[i]); close(ev_array[i].data.fd); continue; } else { buf[s]=0; printf("%s\n",buf); } } else if(ev_array[i].events & EPOLLOUT) { char* buf = "hello word"; write(ev_array[i].data.fd,buf,strlen(buf)); epoll_ctl(epfd,EPOLL_CTL_DEL,ev_array[i].data.fd,&ev_array[i]); close(ev_array[i].data.fd); printf("client is quited\n"); continue; } }//for } }//switch } return 0; }
相关文章推荐
- Linux epoll服务器、epoll、poll、select优缺点
- Linux epoll服务器、epoll、poll、select优缺点
- Linux epoll服务器、epoll、poll、select优缺点
- Linux Socket 多并发服务器开源代码:xSocketd 实现PPC/TPC/SELECT/POLL/EPOLL
- Linux I/O复用中select poll epoll模型的介绍及其优缺点的比较
- Linux——高性能服务器编程——select&poll&epoll
- Linux I/O复用中select poll epoll模型的介绍及其优缺点的比較
- [笔试题 11][linux]select ,poll, epoll(转)
- Linux下多路复用IO接口 epoll select poll 的区别
- [nginx] Linux下多路复用IO接口 epoll select poll 的区别
- Linux程序设计之套接字: select & poll & epoll
- Linux中select poll和epoll的区别
- libevent库源码学习-poll/select( linux) .devpoll(/dev/poll)( linux) ,epoll(linux)
- Linux中select poll和epoll的区别
- Linux中select poll和epoll的区别
- Linux中select poll和epoll的区别
- [转载] Linux下多路复用IO接口 epoll select poll 的区别
- Linux下网络编程(select/poll/epoll)
- Linux中select poll和epoll的区别
- Linux I/O多路复用之select,poll与epoll区别