基本概念:
•流:文件、套接字、管道…
•I/O操作:read/write
•阻塞I/O:一个线程只能处理一个流的I/O事件(多线程pthread_create效率低)
epoll: event poll
•不同于忙轮询和无差别轮询,epoll之会把哪个流发生了怎样的I/O事件通知我们。此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))
简单示例:
•epoll_create 创建一个epoll对象,一般epollfd = epoll_create()
•epoll_ctl (epoll_add/epoll_del的合体),往epoll对象中增加/删除某一个流的某一个事件
•epoll_ctl(epollfd, EPOLL_CTL_ADD, socket, EPOLLIN);//注册缓冲区非空事件,即有数据流入
•epoll_ctl(epollfd, EPOLL_CTL_DEL, socket, EPOLLOUT);//注册缓冲区非满事件,即流可以被写入
•epoll_wait(epollfd,…)等待直到注册的事件发生

非阻塞忙轮询的I/O方式:

#不停的把所有流从头到尾问一遍,又从头开始。这样就可以处理多个流了

如果所有的流都没有数据,那么只会白白浪费CPU
whiletrue{
fori in stream[]; {
ifi has data:
read until unavailable
}
}

无差别轮询的I/O方式:

#在空闲的时候,会把当前线程阻塞掉
#当有一个或多个流有I/O事件时,就从阻塞态中醒来,于是我们的程序就会轮询一遍所有的流。O(n)的无差别轮询复杂度
whiletrue
{
select(streams[])
fori in streams[]
{
ifi has data
read until unavailable
}
}

有意义轮询的I/O方式:

#不同于忙轮询和无差别轮询,epoll之会把哪个流发生了怎样的I/O事件通知我们。此时我们对这些流的操作都是有意义的。复杂度降低到了O(1)
whiletrue
{
active_stream[] = epoll_wait(epollfd)
fori in active_stream[]
{
read or write till
}
}