图解I/O复用并发模型

0 阅读4分钟

网络并发模型中的基本概念:

流:

1).可以进行I/O操作的内核对象.

2).传输媒介可以是文件 管道 套接字等.

3).数据传输入口是通过文件描述符(fd)描述.

I/O操作:

所有对流的读写操作.都可以称为I/O操作.如图所示.

是一个向已经满的流去执行写入操作.所以这次的写入实际上就是一个I/O操作.已经将流写满了.这次写入就会发生阻塞.

如果流为空.在执行读操作.则这次读取操作也是一个I/O操作.也依然会发生阻塞的情况.如图所示.

上面图所示.都是对I/O的操作.当向一个容量已满的传输媒介写数据的时候.这个I/O操作就会发生阻塞.同理.从一个容量为空的传输媒介读取数据的时候.这个I/O操作就会发生读阻塞.

阻塞等待:

假设小G在网上买了一个快递.正好他也没什么事.等得无聊.为了打法空闲时间.就通过睡觉来等待快递.因等待而暂停了其他事情的状态.就是阻塞等待状态.

非阻塞忙轮询:

与阻塞对待相对应的状态是非阻塞忙轮询状态.假设小G性子比较急.每分钟必须给快递员打一次电话.询问多久可以送到.如图所示.

快递员每隔一段时间就会接到电话询问.告诉小G是否到了.此种不间断的的询问对方并且循环往复的状态就是一种非阻塞忙轮询的状态.

阻塞与非阻塞对比:

1).阻塞等待:

空出大脑可以安心睡觉.不影响快递员工作.(不占用CPU宝贵的时间片).

2).非阻塞忙轮询:

浪费时间.浪费电话费.占用快递员时间.(占用CPU及系统资源)

解决阻塞等待缺点的办法:

阻塞死等待的缺点:

同一时刻.小G只能处理一个快递员的签收业务.其他快递员打电话打不进来.所以阻塞等待的问题很明显.小G无法同一时刻解决多个I/O的读写请求.

解决阻塞等待的办法1:多线程/多进程

这种方式就是通过多线程或多进程来处理请求.这种方式没有多路I/O复用情况的解决方案.但是大量的开辟线程或者进程非常浪费资源.一个操作系统能够同时运行的线程和进程都有上限.尤其是进程占用内存的资源极高.这也就限定了能够同时处理I/O数量的瓶颈.

解决阻塞等待的办法2:非阻塞忙轮询

非阻塞忙轮询的方式可以让用户分别于每个快递员取得联系.宏观上来看.是同时可以与多个快递员沟通(并发效果).但是快递员在与用户沟通时会降低前进的速度(浪费CPU).

解决阻塞等待的办法3:select

现在假设可以开一个代收驿站.让快递员将包裹全部放到代收驿站.这个管理员叫select.当有包裹到的时候.select负责给小G打电话.如图所示.

解决阻塞等待的办法4:epoll

现在这个快递代收驿站升级了.服务更加友善且能力更强.与select一样.小G依然可以休息.被动的接收epoll发来的通知.如图所示.

epoll的服务态度要比select好很多.在通知小G的时候.不仅仅告诉快递到了.还会分别告诉是哪几个包裹.

epoll的触发模式:

水平触发:

水平触发的主要特点是.如果用户在监听epoll事件.当内核有事件的时候.则会复制给用户态事件.但是如果用户只处理了一次.则剩下没有处理的将会在下一次epoll_wait再次返回该事件.如下图所示.

这样如果用户永远不处理这个事件.就会导致每次都有该事件从内核到用户的复制.如果所示.耗费性能.但是水平触发相对安全.最起码事件不会丢掉.除非用户处理完毕.

边缘触发:

边缘触发与水平触发相反.当内核有事件到达时.只会通知用户一次.无论用户处理还是不处理.以后都不会在通知.这样减少了复制过程.提高了性能.但是相对来讲.如果用户忘记处理.则会产生丢事件的情况.如图所示.

语雀地址www.yuque.com/itbosunmian…?

《Go.》 密码:xbkk 欢迎大家访问.提意见.

资治通鉴.

如果大家喜欢我的分享的话.可以关注我的微信公众号

念何架构之路