比如 epoll,能管理大量的连接 1.但是有个疑问是,这些连接的处理也是处理器来操作的,也是要耗费大量时间的,为什么使用 epoll 来管理就快了呢,一个个处理不是也是一样的吗? 2.文件描述符 fd 的数据准备好 具体是指什么?磁盘?网络? 3.另外 IO 多路复用是数据的准备操作是在一个线程里处理的吗?还是说 fd 被丢给了其他线程,然后主线程等着数据准备
1
ech0x 2018-11-25 23:03:53 +08:00 via iPhone
没有创建进程 /线程开销
|
2
gamexg 2018-11-25 23:36:47 +08:00 2
特点不是快,而是可以节省系统资源。
最基础的同步阻塞模式意味着随着连接数增加需要增加系统线程,而系统线程成本比较高。 非阻塞模式等于不管有没有数据不断遍历所有 socket,这会浪费 cpu。 epoll 则是非阻塞的优化版本,不用自己去挨个尝试去读取所有 socket 看看哪个可用,系统在 socket 可用时通知应用层。 |
3
lhx2008 2018-11-25 23:51:55 +08:00 via Android
1.原来 IO 没返回要开线程等着,现在线程可以复用了
2.应该是系统的 IO 缓冲区中,对方已经传了一些数据到内存了(不确定,看看楼下大神怎么说),线程可以来拿了 3.应该在系统内核中的线程管理 ,具体原理我也不太清楚 |
4
kran 2018-11-26 00:55:15 +08:00 via Android
不恰当类比一下,吞吐能力上去了,但单个响应不一定快的。
|
5
secondwtq 2018-11-26 00:57:17 +08:00
个人意见:不知道楼主上没上过体系结构的课,我们有一部分是讲 IO 的,当然是硬件层面,先讲了 busy wait 模式,然后说这样会阻塞 CPU 不实用,然后讲了 interrupt 和 DMA 模式,这个是现代 CPU 一直在用的
而在学写 server 时(同样处理 IO 问题),会先学写单线程单请求的,然后是多线程每个线程一个请求的,然后是多路复用的 有没有发现区别 ... 硬件上处理 IO 根本就没有线程的概念,因为主流体系架构使用的 IO 控制机制压根就跟线程没关系(当然 interrupt handler 执行之前会触发 context switch,不过线程建立在此基础之上),用线程来处理 IO 问题的抽象是不合适且不必要的 你可以粗暴的认多路复用是系统提供给用户操作更底层 IO 处理机制的最低成本的一种抽象 |
6
cc959798 OP @gamexg 你好,我可能没表达清楚,其实你说的这些我还是都明白的,可能不明白的是 文件描述符的数据准备这个概念,这个什么叫做数据准备,读磁盘,还是什么,另外如果所有的文件描述符在一个线程里处理,文件准备这个操作也是在同一个线程里处理的,这样连接多了不会也会造成处理的很多连接处理的很慢吗,仅仅是为了省资源?
|
8
gamexg 2018-11-26 10:10:40 +08:00
|
9
cyspy 2018-11-26 10:40:17 +08:00
@cc959798 同步阻塞模式下高并发的时候就不只是慢的问题了, 比如 64bit Java 默认一个线程要 1M 内存,小机器很容易就吃满了
|
10
cc959798 OP @gamexg 你的意思是说,网卡或者说硬件设备数据到达内存或者处理的进程是比较慢的,相比建立连接来说,为了节约这部分时间,我们仅仅 handle 连接,不做处理,仅仅等待他数据到达了我们在处理,也就是说 io 多路复用节约的是这部分时间,对请求的处理该是多少就是多少?
|
11
gamexg 2018-11-26 13:05:26 +08:00
@cc959798 #10
io 多路复用不节省时间,不增加速度。 x 年前单机 10k 连接挑战时,如 @cyspy #9 所说,"比如 64bit Java 默认一个线程要 1M 内存,小机器很容易就吃满了",10k 个连接如果开 10k 个线程,光线程本身就会占用 1M*10k = 10G 内存,非常浪费了。 io 多路复用,复用的是线程。可以理解为使用同步阻塞模式,每个连接 read 都需要一个线程。而使用 io 多路复用意味着一个线程可以处理多个 socket 的 read。这里的意图是节省线程这个成本较高的资源。 然后注意 上个连接中 “调用完 sk_data_ready 之后,一个数据包处理完成,等待应用层程序来读取,上面所有函数的执行过程都在软中断的上下文中。”,也就是在 socket read 准备好之前的所有操作都是内核 ksoftirqd 进程负责的,并不需要用户进程的线程处理。既然之前的操作不需要用户线程,那么为什么要一个连接浪费一个线程等待 read 返回?所以慢慢发展出来了 epoll,一个线程可以等待一批 socket,反正在准备好之前都是内核 ksoftirqd 进程处理,用户线程一直在等待数据准备好,相当于等待一个锁。 |
12
cc959798 OP @gamexg 嗯嗯,谢谢,也就说分两个方面理解,不是加速而是能不能到问题,或者说节省了资源,加快了吞吐让人感觉是变快了,io 多路复用和阻塞着连接是一样的,只不过一个线程处理多个。
另外一个方面是读取网络来的请求时耗时的(不管具体怎样),我们没必要等着,发现有数据准备好的我们就开始读取数据 我一开始可能理解的有些问题,网上的资料都是着重于将 epoll 的原理,其他的不太详细,所以才有疑问😳 一开始想到的是,我们读取请求之后,处理请求都是一样的,无论你 io 多路复用还是阻塞着来,所以感觉总是时间是一样的,忽视了请求到来和读取完毕这个过程中还是有很多工作要做的,所以才疑惑,不过多谢啦 |
13
julyclyde 2018-11-26 15:59:40 +08:00
所谓快是相当于多进程多线程来说的
节省了 CPU 切换进程时的开销 |
14
chashao 2018-11-26 17:59:38 +08:00
我以为 IO 复用是 IO 的速度相对于太慢- -然后让 CPU 等待 IO 完成不值得,这样只能用多线程,但是多线程占用内存多,不过多线程可以让系统来调度,IO 复用就需要自己来维持连接状态- -不知道这样对不对
|