【IO】IO问题进一步思考

问题

问题1:计算机中读写数据的流程是什么?数据走向是什么样的

操作系统主要的设计原则:使用方便,高效工作

CPU是和内存间接交互,还是和磁盘直接交互

DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依于CPU的大量中断负载。否则,CPU需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU对于其他的工作来说就无法使用。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,能使CPU 的效率大为提高。现代操作系统大都支持虚拟内存映射,这样,我们可以把内核空间地址与用户空间的虚拟地址映射到同一个物理地址,这样,DMA 硬件(只能访问物理内存地址)就可以填充对内核与用户空间进程同时可见的缓冲区了。
虚拟内存:https://blog.csdn.net/zhyfxy/article/details/70157248

系统调用是操作系统的最小功能单位

问题2:阻塞和非阻塞区别是什么?

网卡怎么接受数据

1: 数据包从外面的网络进入物理网卡。
2: 网卡将数据包通过DMA的方式写入到指定的内存地址,该地址由网卡驱动分配并初始化。
3: 网卡通过硬件中断(IRQ)通知CPU,告诉它有数据来了(一般而言,由硬件产生的信号需要cpu立马做出回应(不然数据可能就丢失),所以它的优先级很高。cpu理应中断掉正在执行的程序,去做出响应;当cpu完成对硬件的响应后,再重新执行用户程序。中断的过程如下图,和函数调用差不多。只不过函数调用是事先定好位置,而中断的位置由“信号”决定。以键盘为例,当用户按下键盘某个按键时,键盘会给cpu的中断引脚发出一个高电平。cpu能够捕获这个信号,然后执行键盘中断程序。下图展示了各种硬件通过中断与cpu交互。)
4: CPU根据中断表,调用已经注册的中断函数,这个中断函数会调到驱动程序(NIC Driver)中相应的函数
5: 驱动先禁用网卡的中断,表示驱动程序已经知道内存中有数据了,告诉网卡下次再收到数据包直接写内存就可以了,不要再通知CPU了,这样可以提高效率,避免CPU不停的被中断。
6: 启动软中断。这步结束后,硬件中断处理函数就结束返回了。由于硬中断处理程序执行的过程中不能被中断,所以如果它执行时间过长,会导致CPU没法响应其它硬件的中断,于是内核引入软中断,这样可以将硬中断处理函数中耗时的部分移到软中断处理函数里面来慢慢处理。
7: 内核中的ksoftirqd进程专门负责软中断的处理,当它收到软中断后,就会调用相应软中断所对应的处理函数,对于上面第6步中是网卡驱动模块抛出的软中断,ksoftirqd会调用网络模块的net_rx_action函数
8: net_rx_action调用网卡驱动里的poll函数来一个一个的处理数据包
9: 在pool函数中,驱动会一个接一个的读取网卡写到内存中的数据包,内存中数据包的格式只有驱动知道
10: 驱动程序将内存中的数据包转换成内核网络模块能识别的skb格式,然后调用napi_gro_receive函数
11: 待内存中的所有数据包被处理完成后(即poll函数执行完成),启用网卡的硬中断,这样下次网卡再收到数据的时候就会通知CPU

详细过程参考:https://segmentfault.com/a/1190000008836467

应用层一般有两种方式接收数据,一种是recvfrom函数阻塞在那里等着数据来,这种情况下当socket收到通知后,recvfrom就会被唤醒,然后读取接收队列的数据;另一种是通过epoll或者select监听相应的socket,当收到通知后,再调用recvfrom函数去读取接收队列的数据。两种情况都能正常的接收到相应的数据包。

进程阻塞为什么不占用cpu资源?

https://zhuanlan.zhihu.com/p/63179839

https://zhuanlan.zhihu.com/p/64138532

https://zhuanlan.zhihu.com/p/64746509

阻塞和非阻塞有直接的效率区分

单个进程可监视的fd数量被限制,即能监听端口的大小有限。
一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048

当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll与kqueue做的。

系统是如何切换到内核以及如何返回通知的

https://blog.csdn.net/u011846257/article/details/50126125

  1. 系统调用
  2. 异常事件,如缺页异常。
  3. 设备的中断

为什么内核态到用户态切换花费时间

Linux 通过 软中断 实现从 用户态 到 内核态 的切换。 用户态 与 内核态 是独立的执行流,因此在切换时,需要准备 执行栈 并保存 寄存器 。 若每次中断处理平均花 100 微秒

为什么一般要绑定使用线程模型

为什么同步非阻塞IO对磁盘IO不起作用

https://www.zhihu.com/question/52989189?sort=created

内核接收数据包方式

中断方式

2.4之前都是用中断方式接收的。数据包到达网卡后产生一个中断,中断服务程序将接收的数据拷贝到skb,然后将skb挂入软中断队列上,同时将设备poll_list加入软中断的poll_list列表并标记,然后等待软中断处理。发生软中断的时候将skb从软中断队列中取出,发送给网络上层(netif_receive_skb())。

轮询方式

2.6中增加了轮询机制。当中断来临时,它首先直接将设备poll_list挂入软中断的poll_list,打上软中断标记,先不对数据包进行接收,把接收数据包的任务给软中断了。发生软中断时直接把网卡数据poll给skb, 然后交给上层(netif_receive_skb())。
netif_receive_skb()得到skb包之后就处理该数据包, 检查正确性,打印时间戳。

NIO是为了把等待就绪的这段时间让出来,但是磁盘IO是没有就绪这个情况的,都是给磁盘任务队列了,随时他都是就绪的。
传统磁盘硬件概念上是没有轮询这个操作的,但是网络设备设计之初就考虑了延迟的大范围变动和不确定性
磁盘作为一个“不写完不行”的设备,如果中间中断了,碎片问题
最近几年磁盘才把异步接口做到了硬件接口中,即便这样,磁盘IO也不是可检测的异步

问题3:recvfrom/select/poll/epoll在java是怎么用的

用户程序------>C库(即API):INT 0x80 ----->system_call------->系统调用服务例程-------->内核程序

/usr/include/x86_64-linux-gnu/sys

/openjdk/hotspot/src/os/bsd/vm

为什么nodejs用的是单线程模型,nodejs在程序启动之时,就会创建一个类似while(true)的循环,来检测是否有事件需要处理,

一个server对应多个client,端口问题

问题4:为什么netty用NIO,而不是AIO

  • Not faster than NIO (epoll) on unix systems (which is true)
  • There is no daragram suppport
  • Unnecessary threading model (too much abstraction without usage)

https://github.com/netty/netty/issues/2515

图片

其他

  1. jvm为什么要使用堆外内存,堆外内存如何做数据拷贝
  2. netty的零拷贝是真的零拷贝么?是怎么实现的?

参考:
https://juejin.im/entry/5b558d62e51d4519596b95c5
https://juejin.im/post/5c1c532551882579520b1f47?utm_source=gold_browser_extension
http://t.zijieimg.com/PRUmFN/

链接

https://segmentfault.com/q/1010000000190024
https://blog.csdn.net/yezhenxu1992/article/details/51731237
https://www.cnblogs.com/pugang/p/5874958.html
https://zhidao.baidu.com/question/362861325111120052.html
https://www.cnblogs.com/bhlsheji/p/5330045.html
https://blog.csdn.net/wenqian1991/article/details/46546477
https://blog.csdn.net/yexiangCSDN/article/details/86071119
https://www.cnblogs.com/mike-mei/p/8548238.html
https://zhidao.baidu.com/question/377985345.html
https://stackoverflow.com/questions/3329641/how-do-multiple-clients-connect-simultaneously-to-one-port-say-80-on-a-server
http://www.voidcn.com/article/p-wprindkq-bgg.html
https://www.sohu.com/a/142000391_505795
https://www.cnblogs.com/jiangxinlingdu/p/8520322.html
https://www.cnblogs.com/fasionchan/p/9431784.html
https://blog.csdn.net/JH_Zhai/article/details/79861169
https://blog.csdn.net/clever_wr/article/details/82713353
https://blog.csdn.net/qq_41792038/article/details/89814038
https://blog.csdn.net/qwe6112071/article/details/71822185
https://zhidao.baidu.com/question/196573574.html
https://www.cnblogs.com/wuyida/archive/2012/12/29/6301060.html
https://www.cnblogs.com/yfceshi/p/6885322.html
https://www.zhihu.com/question/37271342?sort=created
https://blog.csdn.net/u011846257/article/details/50126125
https://blog.csdn.net/zhejfl/article/details/82555634
https://www.zhihu.com/question/52989189?sort=created
https://blog.51cto.com/12814931/2137378
https://www.cnblogs.com/aspirant/p/9166944.html
https://blog.csdn.net/ZYZMZM_/article/details/90413967
https://www.cnblogs.com/gaopeng527/p/4896783.html
https://zhuanlan.zhihu.com/p/64746509
https://segmentfault.com/a/1190000008836467

posted @ 2019-09-02 18:33  colin_xun  阅读(385)  评论(0编辑  收藏  举报