目录
一、基础知识
首先要知道,服务器与客户端的网络通信。服务器首先要创建一个socket用于指定需要监听的ip地址和端口。其中主机ip对应了一台主机,而ip+端口对应了一台主机上的某一个应用程序。当服务器将需要监听socket的文件描述符与监听的ip+端口绑定起来时,服务器就可以开启监听。此时客户端便可以连接上服务器这个端口。服务器利用accept查看监听端口中是否有输入事件,如果有就说明有新的客户端连接请求,并会开启一个新的文件描述符用于服务器和客户端的读写操作了。
selelct 模型,poll模型,epoll模型 为网络通信中的IO多路复用方法。是为了提高网络通信并发量和通信效率而生的。除了IO多路复用方法,还可以利用多线程,多进程等方式,但是效果都不如IO多路复用。
select模型,poll模型,epoll模型 首先也要经历创建监听socket,监听socket绑定主机和端口,开启监听,accept客户端连接这些阶段。它们和一般网络通信区别在于如何管理这些多个网络通信连接,使通信过程高效。
在主机上的ip和端口用的是主机字节序,而网络上的通信用的是网络字节序。网络字节序采用大端的方式,即高位字节排放在内存的低地址端(即该值的起始地址),低位字节排放在内存的高地址端。而主机字节序根据CPU种类可能有小端模式或者大端模式。
二、select 模型服务流程
1.select模型在accpet一堆客户端连接后,便把这些与客户端通信的文件描述符放进fd_set进行管理。fd_set是一个bitmap,哪些文件描述符被加入到fd_set中,该文件描述符在fd_set对应的bit位就会置为1.
2.select 函数首先会把fd_set从用户态拷贝进内核态。由内核负责遍历哪一个文件描述符中有数据到达。没有数据就进行阻塞。其中第一个参数 maxfd,用于限定遍历范围,指定从0开始到maxfd之前的文件描述符进行遍历。
3.如果没数据,进程就会进入阻塞状态,并将改进程放入socket的等待队列中。等待客户端把数据发送过来。
4.网卡接受到了一个或多个客户端发来的数据。此时会产生一个中断,并且调用DMA拷贝,将网卡收到的数据,拷贝到内核环形缓冲区,而后再根据文件描述符信息放入对应的数据接收队列中。并唤醒进程。
5.如果遍历中发现了多个客户端通信的文件描述符有接收到数据。那么select 函数就会修改fd_set,将有数据的文件描述符对应的bit位置为1,其他bit位置0. 。而后将修改后的fd_set拷贝会用户态,并return有数据的文件描述符的个数。
6.应用程序可以遍历修改后的fd_set中的bit位,或者遍历文件描述符,判断哪些描述符中有对应的事件发生。而后可以开始与对应的客户端读写数据。
二、select 模式的缺点。
1.由于fd_set是bitmap,通常的最大容量为1024个bit位,意味着最多遍历1024个文件描述符。有最大连接限制。
2.由于fd_set传进select函数中为引用传递,每次循环都要重新赋值fd_set,无法重用。
3。频繁进行用户态和内核态的,当连接多时开销大。
4. 应用程序的轮询就绪的文件描述符的时间复杂度为O(n).
三、poll 概要
poll流程和select模型流程大多都一样。都要建立监听,accept客户端连接,把客户端连接放在一个集合中,再将集合放到模型中管理,最后遍历有事件的文件描述符,进行通信。
poll流程和select模型不一样的地方。也就是将集合fd_set 替换成pollfd。也就是poll模型不用bitmap了,而是用一个pollfd的结构体进行操作。再pollfd中设置需要注册的事件events,而,poll函数中不修改events属性,而是修改revents属性来表示发生的事件。 在客户端响应后只需要重置revents就可以达到重用效果。
1.由于pollfd不再是bitmap,而是一个结构体,再poll模型中,内核态采用链表的形式对accept进来的socket进行管理,意味着再内存允许的范围内不再限制最大连接数。
2.pollfd传进poll函数中为引用传递,但是poll不会修改注册的监听事件属性,可以达到重用的效果。
3。依旧频繁进行用户态和内核态的,当连接多时开销大。
4. 时间复杂度依旧为O(n).
四、epoll 服务端实现流程
和正常网络服务端程序一样,服务端首先要创建一个socket用于监听,其中socket地址指定需要监听的主机和程序对应的端口。并与socket对应的文件描述符绑定起来。而后利用epoll函数对网络通信的文件描述符管理起来。
首先要了解epoll的数据结构,对epoll数据结构的管理和具体操作都是在内核态进行,操作系统对epoll管理都已经封装好了,程序员只需要负责调用就行。epoll的数据结构主要包括:
1.存放已就绪事件的就绪队列,它是双向链表构成的。
2.用于管理socket的红黑树。
3.以及双向链表表示的阻塞进程的队列。
程序员可对epoll的操作主要是3种:
1.epoll_create:
在epoll文件系统建立了个file节点(B+树),并开辟epoll自己的内核高速cache区,建立红黑树,建立双向链表用于存储准备就绪的事件。其中
首先创建一个struct eventpoll对象;然后分配一个未使用的文件描述符;然后创建一个struct file对象,将file中的struct file_operations *f_op设置为全局变量eventpoll_fops,将void *private指向刚创建的eventpoll对象ep;然后设置eventpoll中的file指针;最后将文件描述符添加到当前进程的文件描述符表中,并返回给用户。因为内核初始化时(操作系统启动)注册了一个新的文件系统,叫"eventpollfs"专门由于服务epoll。返回的fd就是该文件系统新建的文件描述符
2.epoll_ctl
epoll_ctl()首先判断op是不是删除操作,如果不是则将event参数从用户空间拷贝到内核中;获得struct eventpoll对象,接下来会