当前位置: 技术问答>linux和unix
Epoll的程序设计问题,尽量讲清晰点,大家帮忙解答,谢谢.
来源: 互联网 发布时间:2016-12-16
本文导语: Epoll有两种模式: 1,ET:有数据到来只通知一次,直到本次通知的内容读完(非阻塞读到EWOULDBLOCK/EAGAIN)才会再次给与通知. 2, LT:只要有数据,就不停的通知,和Select/Poll相同。 我的设计分为三部分: 主线程的Epoll调用,读...
Epoll有两种模式:
1,ET:有数据到来只通知一次,直到本次通知的内容读完(非阻塞读到EWOULDBLOCK/EAGAIN)才会再次给与通知.
2, LT:只要有数据,就不停的通知,和Select/Poll相同。
我的设计分为三部分: 主线程的Epoll调用,读数据线程池,处理数据线程池。
问题:
1,ET模式下,一批数据到来,我读了一半,下一次epoll不会再给通知。 但如果此时又来了新的一批数据,请问会不会通知。 也就是说,Epoll是根据描述符上出现EWOULDBLOCK错误判断通知能否继续还是根据数据的到来批次决定是否通知?
(注:第一批数据到来之后,我没有取消EPOLLIN事件)
2,Epoll监测多个TCP客户SOCKET,客户以命令的方式发送数据到服务器,读数据线程池需要抽取一个线程做TCP客户命令的解析并拆分成逐条命令存储起来。
我当然希望同一时刻,一个TCP客户只对应一个读线程,并且不丢失客户数据。
设计一:Epoll检测到客户A送来数据,于是唤醒线程T1进行读取(非阻塞循环读到EWOULDBLOCK)。 在T1线程仍在读取数据的时候,主函数线程依旧在运行中,如果此时客户A再次到来数据,如果问题1的答案是:“是”,Epoll又会再次通知,程序会唤醒T2也读A的数据,T1,T2都读客户A肯定不行。 如果问题1的答案是:“否”,Epoll不会再次通知,直到T1读出EWOULDBLOCK 时 Epoll才会在下一次调用中发起通知,那么问题就不存在了。
设计二:Epoll在检测到客户A有数据后,唤醒线程T1,然后取消该套接字的EPOLLIN选项,即在以后的Epoll中不再检测A是否有数据到来,直到线程T1发生EWOULDBLOCK后,在线程内重新设置该套接字的EPOLLIN选项。 于是Epoll在以后的调用中,如果有数据到来,便可再次给出通知。
设计三:Epoll在检测到客户A有数据后,加锁检测全局标记,如果客户A的SOCKET没有被标记,那么标记它,并唤醒线程T1读取数据。 线程T1读数据到EWOULDBLOCK之后,加锁取消该SOCKET的标记,这样以后便可以保证同一时刻一个SOCKET只对应一个线程。
我假设使用的都是ET模式,因为ET+非阻塞套接字已经完全可以不丢失数据,而LT+非阻塞套接字显得LT毫无意义,更不用说LT+阻塞套接字这样毫无意义的。
1,ET:有数据到来只通知一次,直到本次通知的内容读完(非阻塞读到EWOULDBLOCK/EAGAIN)才会再次给与通知.
2, LT:只要有数据,就不停的通知,和Select/Poll相同。
我的设计分为三部分: 主线程的Epoll调用,读数据线程池,处理数据线程池。
问题:
1,ET模式下,一批数据到来,我读了一半,下一次epoll不会再给通知。 但如果此时又来了新的一批数据,请问会不会通知。 也就是说,Epoll是根据描述符上出现EWOULDBLOCK错误判断通知能否继续还是根据数据的到来批次决定是否通知?
(注:第一批数据到来之后,我没有取消EPOLLIN事件)
2,Epoll监测多个TCP客户SOCKET,客户以命令的方式发送数据到服务器,读数据线程池需要抽取一个线程做TCP客户命令的解析并拆分成逐条命令存储起来。
我当然希望同一时刻,一个TCP客户只对应一个读线程,并且不丢失客户数据。
设计一:Epoll检测到客户A送来数据,于是唤醒线程T1进行读取(非阻塞循环读到EWOULDBLOCK)。 在T1线程仍在读取数据的时候,主函数线程依旧在运行中,如果此时客户A再次到来数据,如果问题1的答案是:“是”,Epoll又会再次通知,程序会唤醒T2也读A的数据,T1,T2都读客户A肯定不行。 如果问题1的答案是:“否”,Epoll不会再次通知,直到T1读出EWOULDBLOCK 时 Epoll才会在下一次调用中发起通知,那么问题就不存在了。
设计二:Epoll在检测到客户A有数据后,唤醒线程T1,然后取消该套接字的EPOLLIN选项,即在以后的Epoll中不再检测A是否有数据到来,直到线程T1发生EWOULDBLOCK后,在线程内重新设置该套接字的EPOLLIN选项。 于是Epoll在以后的调用中,如果有数据到来,便可再次给出通知。
设计三:Epoll在检测到客户A有数据后,加锁检测全局标记,如果客户A的SOCKET没有被标记,那么标记它,并唤醒线程T1读取数据。 线程T1读数据到EWOULDBLOCK之后,加锁取消该SOCKET的标记,这样以后便可以保证同一时刻一个SOCKET只对应一个线程。
我假设使用的都是ET模式,因为ET+非阻塞套接字已经完全可以不丢失数据,而LT+非阻塞套接字显得LT毫无意义,更不用说LT+阻塞套接字这样毫无意义的。
|
即使采用设计3,是不是也有一个数据边界的问题..
读线程与处理线程通过队列交互吗?
如果是的话,那读数据线程什么时候把数据放入队列?
读线程与处理线程通过队列交互吗?
如果是的话,那读数据线程什么时候把数据放入队列?
|
如果第一批数据10个字节,触发通知之后,读线程T1读了5个字节
此时第二批数据又发来10个字节,再次触发通知,还是让T1继续读
那么最终T1读了20个字节,这20个字节包含两个请求消息,一起放入队列吗?
还是拆分为两条独立的消息后放入队列?如何拆分?
此时第二批数据又发来10个字节,再次触发通知,还是让T1继续读
那么最终T1读了20个字节,这20个字节包含两个请求消息,一起放入队列吗?
还是拆分为两条独立的消息后放入队列?如何拆分?