标签:触发 IO epoll 复用 边沿 缓冲区 buf 字节
epoll有两种触发模式 : 水平触发和边沿触发. 默认为水平触发模式.
水平触发
什么叫做水平触发呢? IO大都有缓冲区, 当缓冲区里面只要有数据时就会触发水平模式,直到将缓冲的数据读写结束才不会触发水平模式.
举个栗子 : 当我们现在的读缓冲区有1024字节的数据而我们每次都只能读一个字节, 那么一次读操作后缓冲区还有1023字节, 此时又继续触发水平模式继续读, 直到1024字节读完才不会触发水平模式.
因为默认是水平默认, 所以我们现在做的实验并容易引起大家的感觉. 实验代码只将服务端的buf[1024]改为了buf[2] ,完整代码epoll_default.c
客户端发送一串字符后也收到了完整的字符串. 运行结果 :
边沿触发
什么叫边沿触发呢? IO大都有缓冲区, 当缓冲区发生变化才会触发边沿模式.
举个栗子 : 我们每次都只能读一个字节. 当现在的读缓冲区增加到了1024字节的数据, 缓冲区有改变了那么触发边沿模式读一个字节, 操作后缓冲区还有1023字节. 但是现在缓冲区没有变化了, 所以不再触发边沿模式, 剩下的1023字节只有留在缓冲区中.
通过设置event
事件为EPOLLET才开启边沿触发.
完整代码epoll_ET.c. 只将服务端的buf[1024]改为了buf[2]并设置了EPOLLET.
void doService(int servicefd)
{
char buf[2]; // 设置为2
while(1)
{
eventNum = epoll_wait(epfd, evts, EPOLL_MAX, -1);
if(eventNum == 0)
continue;
else if(eventNum < 0)
EXIT("epoll_wait");
for(int i = 0; i < eventNum; i++)
{
if(evts[i].data.fd == servicefd && (evts[i].events &EPOLLIN))
{
clientfd = Accept(servicefd, NULL, NULL);
event.events = EPOLLIN | EPOLLET; // 设置为边沿触发
event.data.fd = clientfd;
epoll_ctl(epfd, EPOLL_CTL_ADD, clientfd, &event);
}
else if(evts[i].events & EPOLLIN)
{
n = recv(evts[i].data.fd, buf, sizeof(buf), 0);
if(n <= 0)
{
epoll_ctl(epfd, EPOLL_CTL_DEL, evts[i].data.fd, NULL);
close(evts[i].data.fd);
fprintf(stderr, "peer close\n");
}
send(evts[i].data.fd, buf, n, 0);
}
}
}
}
运行结果 :
可以看出发送了1234567890但是一次客户端只会发送两个字节过来. 再看当客户端没有接收到所有的字符后关闭服务端也会被意外的关闭, 因为客户端发送了RET段. 当然这只是代码的问题, 大家可以自行修改.
注意
现在没有证实过边沿触发和水平触发哪一个更好, 一般我们都采用默认的水平触发就足够了.
总结
理解什么是水平触发, 什么是边沿触发.
- 水平触发
- 边沿触发
标签:触发,IO,epoll,复用,边沿,缓冲区,buf,字节 来源: https://blog.csdn.net/Function_Dou/article/details/88363852
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。