epoll和select的简单理解

IO多路复用,epoll、poll、select的区别

目前服务器主要采取接收请求的方式主要有三种,多线程接收请求,
select, epoll。

理解:

  1. io多路复用:https://blog.csdn.net/qq_28229449/article/details/85052922,阻塞io和io多路复用的区别是,多路io复用能够阻塞监听多个文件描述符。所以才能多路复用。
  2. select 首先将文件描述符数组copy到内核态中,等到文件描述符中有事件就绪,内核遍历文件描述符数组到返回就绪文件描述符个数,随后用户态再次进行文件描述符遍历。
  3. poll和select区别是,poll利用链表存储文件描述符,没有大小限制
  4. epoll是在内核态维护了文件描述符集合(利用红黑树存储), epoll采用的是事件驱动机制,不需要通过轮询来找到对应的那个文件描述符。当某个文件描述符就绪的时候,会通过回调函数,把它放到一个就绪链表中记录起来,内核就不用遍历文件描述符了。
    内核只返回就绪的文件描述符集合,也就是上面提到的那个就绪链表,因为返回给用户态的肯定是已经就绪了的,所以用户态可以拿来即用,也无需做多余的遍历。
  5. 内核阻塞还是while,这点还是不理解,个人理解select时,有文件描述符就绪唤醒阻塞线程(改变线程状态标志??),线程遍历文件描述符数组,返回就绪文件描述符个数。而epoll文件描述符就绪时,出发回调函数,将文件描述符放置到就绪链表中。内核返回就绪链表给用户态,用户态无需做多余遍历。

Socket常见函数

1.创建serverSocket
2.bing (ip, port)
3. listen(serversocket的文件描述符,全链接队列长度),(设置里全链接队列长度),此时如果有请求来,内核已经帮助完成三次握手。
4. 在执行accept函数前就完成了
5. accept()函数从全连接队列取出一个socket连接,并绑定一个描述符d。(代表着服务端与客户端的连接)。
6. 利用文件描述符d,收发数据。

6.close函数,发生4次挥手。(客户端发送FIN, 进入FIN_WAIT_1状态, 收到ack进入FIN_WAIT_2状态,因为一般server会直接发回ACK, 所以WAIT1状态很难见到, 收到ACK后,客户端进入FIN_WAIT_2状态,server进入ClOSE_WAIT状态,表示还有数据要发送,server发送完数据,发送和FIN报文, 客户端接收到FIN报文后,发送给服务端ACK, 变成TIME_WAIT状态, TIME_WAIT一般存在两个2MSL时间,原因是避免发送给服务端的ACK丢失,继续接收到服务端PIN请求,无法处理。保证Server端连接能够关闭。

Select函数博客地址

https://www.cnblogs.com/Anker/archive/2013/08/14/3258674.html

poll博客地址

https://www.cnblogs.com/Anker/archive/2013/08/15/3261006.html

epoll博客地址

https://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html

区别:https://www.cnblogs.com/sky-heaven/p/7011684.html

select函数:
1.每次select文件描述符集合都发生了变化,要重新复制。
2 .select函数每次调用都要拷贝serverSocket的文件描述符和客户端的文件描述符集合到内核中,内核遍历文件描述符,然后将每个文件描述符的等待队列放入当前进程(注意此时进程并为阻塞)。当文件描述符事件就绪时(内核会控制监听文件描述符的事件),唤醒等待队里当前进程,进程开始遍历文件描述符。
3. 每次内核遍历文件描述符时,还会看文件描述符事件是否就绪,如果就绪重新给文件描述符集合赋值(这就话理解为)可能会改变文件描述符的状态,方便判断是否就绪。
4. 如果没有就绪,则阻塞,等待操作系统唤醒等待进程,重新遍历文件描述符的过程。
5. 理解:遍历文件描述符时,一边会将进程加入等待队列,一边会判断文件描述符事件是否就绪。

poll函数与select的区别是大小没有限制

epoll函数:
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);

a.int epoll_create返回的是一个存储着(文件描述符集合想对应的监听事件)的句柄,size表示句柄对应集合能够存储文件描述符的大小。
b.int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event), epoll_ctl表示将文件描述符fd和对应事件event,绑定到epfd上。
c.i nt epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout),会返回就绪事件的个数,就绪事件在event中。

epoll每次将进程挂载在设备描述符的等待队列只挂载一次,通过句柄epfd管理事件, 每次事件就绪后唤醒,阻塞进程current,并将就绪文件描述符相关事件,加入到就绪集合中, current去检测是就绪集合每次被唤醒,只是去检测就绪集合是否为空,不为空则返回就绪事件,而select每次被唤醒要遍历一面在内核中的文件描述符,导致性能消耗。
epoll用一个描述符epfd管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值