对epoll总结
来源:互联网 发布:java终止for无限循环 编辑:程序博客网 时间:2024/04/30 13:23
epoll是Linux特有的I/O复用函数(个人通过搜索资料和听老师讲解认为epoll相较于select和poll要更加优秀)。
epoll与poll和select的区别是他是用一组函数完成的任务而不是单个函数。
epoll把用户关心的文件描述符上面的事件放在内核里的一个时间表上,故epoll需要一个额外的文件描述符,来唯一标识这个时间表。
#include <sys/epoll.h>
int epoll_create(int size);
size给内核提示事件表需要多大。该函数返回的文件描述符将用作其他epoll函数调用的第一个参数,以指定要访问的内核事件表。
#include <sys/epoll.h>
int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event)
epfd是上面一个epoll_create的返回值
fd表示要操作的文件描述符
op指定操作类型 EPOLL_CTL_ADD 往事件表中注册fd上的事件
EPOLL_CTL_MOD修改fd上的注册事件
EPOLL_CTL_DEL删除fd上的注册事件
event指定事件,表示他的宏就是在poll前面加上E,这里不做列举。
#include <sys/epoll.h>
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
成功则返回就绪文件描述符的个数,失败返回-1。
timeout与poll相同
maxevents指定最多监听多少个事件,必须大于0
epoll的两种模式 LT ET
LT:默认工作模式,仅仅相当于一个较高效的poll。
ET:epoll的高效模式,实现方法是往epoll内核时间表中注册一个文件描述符上的EPOLLET事件。
LT:通知一次,如果你不进行处理那么就一直通知下去。
ET:通知一次,不处理后续的epoll_wait也不会再次的去通知。
由于ET降低了同一个epoll事件被重复触发的次数,因此效率要比LT模式高。
关于epoll监听其他进程的代码
#include <sys/epoll.h>
#include <sys/socket.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
void setnonblock(int fd)
{
int s_flg = fcntl(fd,F_GETFL);
int t_flg = s_flg|O_NONBLOCK|EPOLLRDHUP;
fcntl(fd,F_SETFL,t_flg);
}
void fd_del(int epfd,int fd)
{
if(epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL)==-1)
{
perror("epollctl del error");
}
}
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in saddr,caddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6500);
saddr.sin_addr.s_addr = inet_addr("192.168.1.11");
int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
assert(res!=-1);
listen(sockfd,5);
int epfd = epoll_create(1);//I just need one.只监听一个事件
assert(epfd!=-1);
struct epoll_event ev;
ev.events = EPOLLIN|EPOLLET;//open ET
ev.data.fd = sockfd;
int a = epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ev);//add,开始监听sockfd这个描述符的变化
assert(a!=-1);
setnonblock(sockfd);
struct epoll_event evs;
while(1)
{
int n = epoll_wait(epfd,&evs,1,0);
int fd = evs.data.fd;
if(n==-1)
{
perror("epoll_wait error!\n");
continue;
}
//because the timeout is 0 so do not do anything when the n is 0
if(n>0)
{
if(evs.events&EPOLLRDHUP)
{
fd_del(epfd,fd);
close(fd);
printf("client RDHUP over!\n");
continue;
}
if(evs.events&EPOLLIN)
{
if(fd==sockfd)//监听到了有新的客户端请求链接
{
int len = sizeof(caddr);
int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
if(c<0)
{
continue;
}
struct epoll_event ev2;
ev2.events = EPOLLIN|EPOLLET|EPOLLRDHUP;
ev2.data.fd = c;
epoll_ctl(epfd,EPOLL_CTL_ADD,c,&ev2);//链接成功开始监听这个链接的变化
setnonblock(c);
}
else
{
while(1)//这里只考虑了对面发送信息的变化和断开连接的变化
{
char buff[128] = {0};
int num = recv(fd,buff,127,0);
if(num==0)
{
fd_del(epfd,fd);
close(fd);
printf("one client over\n");
break;
}
else
{
printf("%s",buff);
}
}
}
}
}
}
return 0;
}
相应客户端和上两篇文章的客户端一致,关于epoll会用高效模式就好了,低效的你可以了解,毕竟用的时候肯定会更喜欢效果卓越的用法。
http://www.cnblogs.com/zhangmo/archive/2013/04/02/2995645.html
epoll之所以高效的原因
http://blog.csdn.net/russell_tao/article/details/7160071
- 对epoll总结
- epoll总结
- epoll总结
- epoll总结
- epoll总结
- EPOLL使用总结
- EPOLL使用总结
- select,poll,epoll总结
- Epoll学习总结
- epoll使用及总结
- Epoll归纳总结
- epoll()函数总结
- epoll特点总结
- 多路复用epoll()总结
- select、poll、epoll总结
- epoll基础总结
- epoll总结 一
- Epoll实验总结
- Gallery实现幻灯片式的图片浏览器
- SOJ4509: Snowdrop修长廊 ( 斜率优化DP)
- Caffe中的优化方法
- ruby 数据sql操作ActiveRecord
- 使用onclick跳转到指定页面的方法
- 对epoll总结
- nyoj 14 会场安排问题
- StringBuffer、StringBuilder和BigDecimal
- 学习资料整理汇总(不断更新中)
- Hibernate配置级联的一些问题及cascade与inverse的详解
- 系统架构师谈企业应用架构之业务逻辑层
- 解决Spring MultipartResolver和ServletFileUpload 冲突
- 遍历listview里面全部(可见和不可见)item,从而获取item的信息最简单的方法
- python爬虫抓取游民星空每日囧图