Linux网络编程中的五种I/O模型

1. 最通俗的方式讲解 什么是阻塞/非阻塞,什么是同/异步

使用最通俗概念讲解 同步异步、堵塞和非堵塞

洗衣机洗衣服 (无论阻塞式IO还是非阻塞式IO,都是同步IO模型)

  1. 同步阻塞:你把衣服丢到洗衣机洗,然后看着洗衣机洗完,洗好后再去晾衣服(你就干等,啥都不做,阻塞在
    那边)

  2. 同步非阻塞:你把衣服丢到洗衣机洗,然后会客厅做其他事情,定时去阳台看洗衣机是不是洗完了,洗好后再
    去晾衣服(等待期间你可以做其他事情,比如用电脑打开小D课堂看视频学习)

  3. 异步阻塞: 你把衣服丢到洗衣机洗,然后看着洗衣机洗完,洗好后再去晾衣服(几乎没这个情况,几乎没这个
    说法,可以忽略)

  4. 异步非阻塞:你把衣服丢到洗衣机洗,然后会客厅做其他事情,洗衣机洗好后会自动去晾衣服,晾完成后放个
    音乐告诉你洗好衣服并晾好了

IO操作分两步:发起IO请求等待数据准备,实际IO操作(洗衣服,晾衣服)
同步须要主动读写数据,在读写数据的过程中还是会阻塞(好比晾衣服阻塞了你)
异步仅仅须要I/O操作完毕的通知。并不主动读写数据,由操作系统内核完毕数据的读写(机器人帮你自动晾衣服)

五种IO的模型:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO和异步IO
前四种都是同步IO,在内核数据copy到用户空间时都是阻塞的

1)阻塞式I/O;
在这里插入图片描述

2)非阻塞式I/O;
在这里插入图片描述

3)I/O复用(select,poll,epoll…);

  • I/O多路复用是阻塞在select,epoll这样的系统调用,没有阻塞在真正的I/O系统调用如recvfrom
  • 进程受阻于select,等待可能多个套接口中的任一个变为可读
  1. IO多路复用使用两个系统调用(select和recvfrom)
  2. blocking IO只调用了一个系统调用(recvfrom)
  3. select/epoll 核心是可以同时处理多个connection,而不是更快,所以连接数不高的话,性能不一定比多线程+阻塞IO好
  4. 多路复用模型中,每一个socket,设置为non-blocking,
  5. 阻塞是被select这个函数block,而不是被socket阻塞的

在这里插入图片描述
4)信号驱动式I/O(SIGIO)
在这里插入图片描述

5)异步I/O(POSIX的aio_系列函数) Future-Listener机制
在这里插入图片描述

IO操作分为两步

  1. 发起IO请求,等待数据准备(Waiting for the data to be ready)
  2. 实际的IO操作,将数据从内核拷贝到进程中(Copying the data from the kernel to the process)

前四种IO模型都是同步IO操作,区别在于第一阶段,而他们的第二阶段是一样的:在数据从内核复制到应用缓冲区期间(用户空间),进程阻塞于recvfrom调用或者select()函数。 相反,异步I/O模型在这两个阶段都要处理。

  • 阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。
  • 同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO、非阻塞IO、IO复用、信号驱动IO都是同步IO,如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO。

2. 高并发编程必备知识IO多路复用技术select、poll讲解

2.1 什么是IO多路复用?

I/O多路复用,I/O是指网络I/O, 多路指多个TCP连接(即socket或者channel),复用指复用一个或几个线程。
简单来说:就是使用一个或者几个线程处理多个TCP连接

最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程


select:
基本原理:

  • 监视文件3类描述符: writefds、readfds、和exceptfds
  • 调用后select函数会阻塞住,等有数据 可读、可写、出异常 或者 超时 就会返回
  • select函数正常返回后,通过遍历fdset整个数组才能发现哪些句柄发生了事件,来找到就绪的描述符fd,然后进行对应的IO操作

缺点:

  1. select采用轮询的方式扫描文件描述符,全部扫描,随着文件描述符FD数量增多而性能下降
  2. 每次调用 select(),需要把 fd 集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)
  3. 最大的缺陷就是单个进程打开的FD有限制,默认是1024 (可修改宏定义,但是效率仍然慢)

poll:
基本流程:

  • select() 和 poll() 系统调用的大体一样,处理多个描述符也是使用轮询的方式,根据描述符的状态进行处理
  • 一样需要把 fd 集合从用户态拷贝到内核态,并进行遍历。

最大区别是: poll没有最大文件描述符限制(使用链表的方式存储fd)


epoll:
基本原理:

  • 在2.6内核中提出的,对比select和poll,epoll更加灵活,没有描述符限制,用户态拷贝到内核态只需要一次
  • 使用事件通知,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用callback的回调机制来激活对应的fd

优点:

  1. 没fd这个限制,所支持的FD上限是操作系统的最大文件句柄数,1G内存大概支持10万个句柄
  2. 效率提高,使用回调通知而不是轮询的方式,不会随着FD数目的增加效率下降
  3. 通过callback机制通知,内核和用户空间mmap同一块内存实现

Linux内核核心函数

  1. epoll_create() 在Linux内核里面申请一个文件系统 B+树,返回epoll对象,也是一个fd
  2. epoll_ctl() 操作epoll对象,在这个对象里面修改添加删除对应的链接fd, 绑定一个callback函数
  3. epoll_wait() 判断并完成对应的IO操作

缺点:编程模型比select/poll 复杂


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值