NIO面试题大全

NIO面试题大全


目录

文档索引

面试题汇总

Q:什么是同步、异步、阻塞、非阻塞?

Q:操作系统有哪些IO模型?

Q:多路复用IO模型系统怎么实现?select、poll、epoll区别?

Q:NIO比BIO相比有什么优势?

Q:NIO有哪些组件?

Q:NIO存在哪些问题?

Q:什么是零拷贝?


文档索引


面试题汇总

Q:什么是同步、异步、阻塞、非阻塞?

A: 一次IO的过程主要是:应用向操作系统发起IO指令(read、write),操作系统内核准备数据(把IO外部设备的数据,加载到内核缓冲区),准备完毕后将数据从内核空间复制到用户空间。

内核准备数据过程中,用户进程是否被阻塞

阻塞:用户进程直到内核数据准备完成,才返回

非阻塞:用户进程不等待内核数据准备完成,立即返回

将数据从内核空间复制到用户空间时,用户进程是否被阻塞

同步:用户进程等待数据从内核空间复制到用户空间

异步:用户进程不等待数据复制,内核复制完成后,发送信号通知进程

Q:操作系统有哪些IO模型?

A: 有五种模型:阻塞IO、非阻塞IO、多路复用IO、信号渠道IO、异步IO

阻塞IO:阻塞等待数据准备(阻塞),数据准备好后,等待数据从内核复制到用户空间(同步)

非阻塞IO:不等待数据准备(非阻塞),通过轮询方式判断数据准备好后,等待数据从内核复制到用户空间(同步)

多路复用IO:发生请求后,将socket注册到select,select轮询检查多个socket数据是否准备好(非阻塞),数据准备好后,等待数据从内核复制到用户空间(同步)

信号渠道IO:发生请求后,内核通过信号量标志数据是否准备好(非阻塞),数据准备好后,等待数据从内核复制到用户空间(同步)

异步IO:发生请求后,不等待数据准备(非阻塞),数据准备好后,内核将数据复制到用户空间,然后发送信号通知数据已经复制完成(异步)

Q:多路复用IO模型系统怎么实现?select、poll、epoll区别?

A: 多路复用IO模型目前操作系统有select、poll、epoll三种方式

select:select函数仅仅知道有几个I/O事件发生了,但并不知道具体是哪几个socket连接有I/O事件,还需要轮询去查找,时间复杂度为O(n),处理的请求数越多,所消耗的时间越长。

poll:poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的

epoll:epoll可以理解为event pool,不同与select、poll的轮询机制,epoll采用的是事件驱动机制,每个fd上有注册有回调函数,当网卡接收到数据时会回调该函数,同时将该fd的引用放入rdlist就绪列表中。

当调用epoll_wait检查是否有事件发生时,只需要检查eventpoll对象中的rdlist双链表中是否有epitem元素即可。如果rdlist不为空,则把发生的事件复制到用户态,同时将事件数量返回给用户。

Q:NIO比BIO相比有什么优势?

A: 

1、BIO是面向流的传输;NIO是面向块传输,按块处理数据要比按字节处理数据快得多

2、BIO是采用同步阻塞机制,一个线程资源只能处理一个链接;NIO是采用多路复用IO,可以处理多个链接

3、NIO使用了零拷贝,提高了传输性能

Q:NIO有哪些组件?

A: 

1、Channel

Channel 是对数据的源头和数据目标点流经途径的抽象

ServerSocketChannel:用于监听新的TCP连接的通道,负责读取&相应,通常用于服务端的实现

SocketChannel:用于发起TCP连接,读写网络中的数据,通常用于客户端的实现

2、Selector

Selector是通道注册器,多个Channel均可以注册到Selector,Selector负责监听每个Channel的几个事件:链接就绪、写就绪、读就绪,当某个Channel注册就绪的事件发生,则Selector不再阻塞,返回事件集合,然后按事件不同分发处理

3、Buffer

Buffer就是一个内存块,底层是一个数组。Buffer提供了一组方法轻松使用内存块,Channel读取或写入数据都必须经过Buffer

Q:NIO存在哪些问题?

A: 

1、半包读写

TCP是面向连接的传输协议,TCP传输的数据是以流的形式,而数据流是没有明确的开始结尾边界,所以TCP也没办法判断哪一段流属于哪一个消息,故存在粘包和半包问题

2、断连重连

服务端出现异常时,客户端可能存在连接断开需重新连接的情况

Q:什么是零拷贝?

A: 一次IO读写(如从硬盘发送网卡)的过程:应用发出read指令,CPU进行上下文切换,由用户态转为内核态,CPU通知DMA开始读取数据,DMA从磁盘读取数据到内核缓冲,DMA完成后,向CPU发出中断,CPU从内核缓冲复制到用户缓冲,复制完成后,read指令返回,CPU由内核态转为用户态。

应用发出write指令,CPU进行上下文切换,由用户态转为内核态,CPU从用户缓冲复制到socket缓冲,DMA将socket缓冲写入到网卡,写入完成后,write指令返回,CPU由内核态转为用户态。

故整个IO读写过程涉及两次系统调用,四次上下文切换

通过上面的过程,我们可以看出同样的数据,从内核缓存复制到用户缓冲,再复制到内核缓冲

操作系统提供了mmap,使得应用和操作系统可共享内核缓冲,此时就无需再将数据从内核缓冲复制到用户缓冲,发起write指令后,CPU直接从内核缓冲复制到socket缓冲

但mmap只是减少了一次CPU复制事件,操作系统提供sendfile函数可以减少一次系统调用,发起sendfile后,上下文切换到内核空间,DMA将数据复制到内核缓冲区,CPU将数据从内核缓冲复制到socket缓冲,再经由DMA从socket缓冲复制到网卡,sendfile指令返回,上下文切换到用户空间。

可以发现本次sendfile仅仅发生了2次上下文切换以及3次拷贝(2次DMA拷贝+1次CPU拷贝)

 linux2.4版本后,对sendfile做了优化升级,引入SG-DMA技术,它可以直接从内核空间缓冲区中将数据读取到网卡,这样的话还可以省去CPU拷贝

CPU把内核缓冲区中的文件描述符信息(包括内核缓冲区的内存地址和偏移量)直接发送到socket缓冲区,DMA控制器根据文件描述符信息直接把数据从内核缓冲区拷贝到网卡

可以看到sendfile + DMA发生了2次上下文切换以及2次数据拷贝,全程没有通过CPU来搬运数据,所有的数据都是通过DMA进行传输的,实现了零拷贝

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值