赞
踩
本篇博客由 CSDN@先搞面包再谈爱 原创,转载请标注清楚,请勿抄袭。
本篇主要讲解:
关于多路转接的epoll我会在下一篇详细讲解。
前面我一直在讲网络通信,从创建套接字就可看到网络通信的就是IO,发送方能发也能收,接收方也是能发也能收,站在网络角度来看就是机器把数据扔到了网络里面,站在计算机体系结构角度来看就
是把数据把内存扔到网卡,不管怎么理解,都是IO。
前面文件部分讲过的IO都是文件IO,单机的,打开文件,将数据从磁盘读到os,再从os将数据拷到用户缓冲区,各设备离的都非常近,在网络中,两台主机相隔千里之外,IO效率一定是要比单机来说低不少的。
IO问什么低效?
read、recv、recvfrom、write、send、sendto这样的IO函数本质上都是一些拷贝函数,都是在用户和内核之间拷贝数据,不过毕竟是从内存中直接拷贝的,效率还算OK。
以read为例,当我们进行read/recv的时候,如果底层没有数据,read/recv会怎么办做?有数据又会怎么做?
没有数据,read/recv进程就会阻塞,也就是让进程等。
如果有数据就直接进行拷贝。
⇒ 所以IO就是 等 + 数据拷贝。
等就是等IO类事件就绪。读就是底层有数据,写就是底层有空间。
write也是一样的,缓冲区满了就不让拷贝(等),没满就拷贝,所以IO必须经历的两部就是等和数据拷贝。
看图:
如果进程想要访问磁盘上的文件,那就得先打开这个文件,而文件 = 内容 + 属性,所以打开文件后,os要为文件创建相应的struct FILE结构体以维护文件的属性,也就是在内存中维护,而内存是惰性加载的,不会说将文件中的所有数据全部加载完,因为很多数据不一定能用上,os可能会对文件预加载,也就是先加载一部分,当进程想要修改文件中的内容时,就会先将需要的数据加载到内存里:
此时就是进程先调用的IO类型的函数想要访问文件中的数据,然后os才会做加载的这一步的,也就是os加载之前进程就已经开始调用IO类函数了。
那么os在加载文件的内容时,进程在干嘛?
就是在等。
IO = 等 + 拷贝。上面os在加载的时候,就是等,此刻进程是处于阻塞状态的。
那么拷贝呢?
就是加载完毕之后。进程就会被os唤醒,然后对os加载好的数据进行后续操作。
无论是网络还是单机,只要是访问磁盘、键盘、网卡等等外设,就一定是等 + 数据拷贝。
想一想scanf运行起来之后,为什么会卡在命令行等你输入,其实就是在等待标准输入。cin也是同理,像这样的函数都是在等数据就绪后再将数据从外设搬到内存os的缓冲区中,再从os搬到应用层,这就是数据拷贝。
所以recv、read、send、write等函数看起来是在发送和接收,其实都是在等IO类事件就绪,然后再发起拷贝,拷贝时无非就是从内核到用户或从用户到内核,所以这些函数不是用户直接与硬件进行读写,而是用户和内核之间的“交流”,交流完毕后,os再做后续的事情,比如说将修改后的数据写回磁盘。
在os视角来看,这些函数会让进程阻塞,在IO视角来看就是让进程在等。
网络里面谈IO是因为报文从A主机发送到B主机,中间的发送时间会很长,所以网络通信时调用read、recv等函数就要做IO,这样就会花费大量的时间在等上,如何提高IO的效率呢?只要想办法在单位时间内让等的比重变得越低IO的效率就会越高。
单位时间内让等的比重变低,如何做到呢?
前面大佬们已经对于IO进行了深刻研究,总结出来了五中IO模型,这篇重点要讲的就是这五中IO模型。
先说说都是啥:
不过这里先不说这五种IO模型的细节,我先通过一个生活中的例子来帮大家理解理解。
钓鱼应该都见过吧。这里不说打窝这样的细节,简单一点。
就直接说成等 + 鱼上钩的收杆(后面直接说钓,也就是等 + 钓)。就像mc中的钓鱼一样。
什么场景下会说一个人钓鱼的效率非常高呢?
一个人大半天都没有鱼咬钩,一直在等。
另一个人一直是上钩,不带停的。
很明显,第二个人效率高,所以只要单位时间内等的比重非常低,这个人钓鱼的效率就非常高。
再来介绍个东西,鱼漂,钓鱼佬应该很熟悉,但是没钓过鱼的同学可能很陌生,看图:
钓鱼的时候,鱼漂能够反映出鱼咬钩的讯息。
假如说现在有五个人去钓鱼。
张三钓鱼的时候死死盯住鱼漂,啥也不干,非常专注,鱼漂不动他不动。
李四耐不住性子,看一会手机再看鱼漂有反应没,没反应就接着看手机。
王五拿了个铃铛,挂在鱼杆后面,一直在玩手机,铃铛一响就赶紧收杆。
赵六是个方圆五公里内的富二代,一下子拿了100支鱼竿,安置好后就来回检测哪只哪支鱼竿有鱼咬钩。
田七是个大老板,但是最近想吃鱼了(不是高启强
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。