对于muduo我自己的理解
muduo
的灵魂是 Reactor 模式。
muduo本质就是IO多路复用+EventLoop事件循环+全部非阻塞
在IO多路复用中,使用epoll(和poll,select一样,用于监听多个文件描述符(通常是网络连接)是否准备好进行“读”或“写操作”,即事件是否就绪,让单个线程可以高效地管理大量连接,而不是为每个连接开一个线程),同时IO多路复用中也又检测新事物的连接,也是epoll来干(因为监听套接字也是一个文件描述符fd,当服务器启动时,会创建一个套接字(listen_fd),绑定到某个端口,并调用listen()开始监听,这个listen_fd会添加到epoll
的监控集合中,并告诉 epoll
我们关心的是这个 listen_fd
上的 可读事件,当有新的客户端连接尝试到达服务器端口时,操作系统内核的 TCP/IP 协议栈会完成 TCP 三次握手。一旦握手完成,一个新的连接就建立了。 此时,内核会将这个 listen_fd
标记为 “可读”(EPOLLIN
就绪)。注意:这里的“可读”对于监听套接字的特殊含义是 “有新连接到达,可以调用 accept()
了”。epoll_wait()
函数在检测到这 个 listen_fd
的 EPOLLIN
事件就绪时,就会返回。
服务器程序(具体是
EventLoop
->Poller
->Channel
)发现listen_fd
的EPOLLIN
事件就绪,就会调用预先注册给这个Channel
的 “可读回调函数”。在这个回调函数里(通常是Acceptor::handleRead()
),程序才会调用accept()
系统调用。accept()
会从内核的已连接队列中取出这个新连接,创建一个新的套接字描述符(conn_fd
) 用于和这个特定的客户端通信。这个新创建的conn_fd
会立即被设置为非阻塞模式,并再次添加到epoll
的监控集合中(同样关心EPOLLIN
等事件),后续这个连接的读写事件就由epoll
来监控了。
)
在EventLoop事件循环就是调用epoll_wait,在IO多路复用那里阻塞着。然后还有epoll_wait有个参数timeout,可以设置隔一段时间返回IO多路复用里就绪的事件。
epoll
是 Linux 提供的一种 IO多路复用机制。它本身是一组 系统调用 (epoll_create
, epoll_ctl
, epoll_wait
) 和一个内核数据结构(事件表)。
epoll_wait
是干什么的? 它是 epoll
机制的核心系统调用之一。它的工作就是 阻塞(或等待)在事件表上,直到有注册的事件发生或者超时。