相对同步IO,异步IO在用户进程发起异步读(aio_read)系统调用之后,无论内核缓冲区数据是否准备好,都不会阻塞当前进程;在aio_read系统调用返回后进程就可以处理其他逻辑
socket数据在内核就绪时,系统直接把数据从内核复制到用户空间,然后再使用信号通知用户进程
R1、R2两阶段时进程都是非阻塞的
多路复用IO深入理解一波 select int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);1)使用copy_from_user从用户空间拷贝fd_set到内核空间
2)注册回调函数__pollwait
3)遍历所有fd,调用其对应的poll方法(对于socket,这个poll方法是sock_poll,sock_poll根据情况会调用到tcp_poll,udp_poll或者datagram_poll)
4)以tcp_poll为例,其核心实现就是__pollwait,也就是上面注册的回调函数
5)__pollwait的主要工作就是把current(当前进程)挂到设备的等待队列中,不同的设备有不同的等待队列,对于tcp_poll来说,其等待队列是sk->sk_sleep(注意把进程挂到等待队列中并不代表进程已经睡眠了)。在设备收到一条消息(网络设备)或填写完文件数据(磁盘设备)后,会唤醒设备等待队列上睡眠的进程,这时current便被唤醒了
6)poll方法返回时会返回一个描述读写操作是否就绪的mask掩码,根据这个mask掩码给fd_set赋值
7)如果遍历完所有的fd,还没有返回一个可读写的mask掩码,则会调用schedule_timeout是调用select的进程(也就是current)进入睡眠
8) 当设备驱动发生自身资源可读写后,会唤醒其等待队列上睡眠的进程。如果超过一定的超时时间(timeout指定),还是没人唤醒,则调用select的进程会重新被唤醒获得CPU,进而重新遍历fd,判断有没有就绪的fd
9)把fd_set从内核空间拷贝到用户空间
select的缺点每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
select支持的文件描述符数量太小了,默认是1024
epoll int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);调用epoll_create,会在内核cache里建个红黑树用于存储以后epoll_ctl传来的socket,同时也会再建立一个rdllist双向链表用于存储准备就绪的事件。当epoll_wait调用时,仅查看这个rdllist双向链表数据即可
epoll_ctl在向epoll对象中添加、修改、删除事件时,是在rbr红黑树中操作的,非常快
添加到epoll中的事件会与设备(如网卡)建立回调关系,设备上相应事件的发生时会调用回调方法,把事件加进rdllist双向链表中;这个回调方法在内核中叫做ep_poll_callback
epoll的两种触发模式epoll有EPOLLLT和EPOLLET两种触发模式,LT是默认的模式,ET是“高速”模式(只支持no-block socket)
LT(水平触发)模式下,只要这个文件描述符还有数据可读,每次epoll_wait都会触发它的读事件
ET(边缘触发)模式下,检测到有I/O事件时,通过 epoll_wait 调用会得到有事件通知的文件描述符,对于文件描述符,如可读,则必须将该文件描述符一直读到空(或者返回EWOULDBLOCK),否则下次的epoll_wait不会触发该事件
epoll相比select的优点解决select三个缺点
对于第一个缺点:epoll的解决方案在epoll_ctl函数中。每次注册新的事件到epoll句柄中时(在epoll_ctl中指定EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝。epoll保证了每个fd在整个过程中只会拷贝一次(epoll_wait不需要复制)
对于第二个缺点:epoll为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd(不需要遍历)