在日常 Coding 中,多多少少都会接触到网络 IO,就会想要深入了解一下。看了很多文章,总是云里雾里的感觉,直到读了《UNIX网络编程 卷1:套接字联网API》中的介绍后,才豁然开朗。这里就给大家分享一下,如有不对,欢迎指出。

1. 概念说明

为了便于理解后面的内容,我们先来了解一些概念。

1.1 Socket

Socket 中文翻译为套接字,是计算机网络中进程间进行双向通信的端点的抽象。一个 Socket 代表了网络通信的一端,是由操作系统提供的进程间通信机制。

  • 在操作系统中,通常会为应用程序提供一组应用程序接口,称为 Socket 接口(Socket API)。应用程序可以通过 Socket 接口,来使用网络 Socket,以进行数据的传输。

  • 一个 Socket 由IP地址和端口组成,即:Socket 地址 = IP地址 : 端口号。

  • 在同一台计算机上,TCP 协议与 UDP 协议可以同时使用相同的端口(Port),而互不干扰。

  • 要想实现网络通信,至少需要一对 Socket,其中一个运行在客户端,称之为 Client Socket;另一个运行在服务器端,称之为 Server Socket。

  • Socket 之间的连接过程可以分为三个步骤:(1)服务器监听;(2)客户端连接;(3)连接确认。

1.2 Socket 缓冲区

每个 Socket 被创建后,都会在内核中分配两个缓冲区:输入缓冲区和输出缓冲区。

  • 通过 Socket 发送数据并不会立即向网络中传输数据,而是先将数据写入到输出缓冲区中,再由 TCP 协议将数据从输出缓冲区发送到目标主机。

  • 通过 Socket 接收数据也是如此,也是从输入缓冲区中读取数据,而不是直接从网络中读取。

1.3 用户空间、内核空间、系统调用

操作系统的进程空间可以分为用户空间(User Space)和内核空间(Kernel Space),它们需要不同的执行权限。

  • 大多数系统交互式操作需要在内核空间中运行,比如设备 IO 操作。

  • 我们的应用程序运行在用户空间,是不具备系统级的直接操作权限的。如果应用程序想要访问系统核心功能,必须通过系统调用(System Call)来完成。比如调用recv()函数,会将输入缓冲区中的内容拷贝到用户缓冲区。

  • 系统调用运行在内核空间,是操作系统为应用程序提供的接口。

下面列举了一些 Linux 操作系统中的系统调用接口(部分函数后面章节会用到):

  • socketcall socket系统调用

  • socket 建立socket

  • bind 绑定socket到端口

  • connect 连接远程主机

  • accept 响应socket连接请求

  • send 通过socket发送信息

  • sendto 发送UDP信息

  • recv 通过socket接收信息

  • recvfrom 接收UDP信息

  • listen 监听socket端口

  • select 对多路同步IO进行轮询

  • shutdown 关闭socket上的连接

  • sigaction 设置对指定信号的处理方法

1.4 阻塞与非阻塞

阻塞与非阻塞,用于描述调用者在等待返回结果时的状态。

  • 阻塞:调用者发起请求后,会一直等待返回结果,这期间当前线程会被挂起(阻塞)。

  • 非阻塞:调用者发起请求后,会立刻返回,当前线程也不会阻塞。该调用不会立刻得到结果,调用者需要定时轮询查看处理状态。

1.5 同步与异步

而同步与异步,用于描述调用结果的返回机制(或者叫通信机制)。

  • 同步:调用者发起请求后,会一直等待返回结果,即由调用者主动等待这个调用结果。

  • 异步:调用者发起请求后,会立刻返回,但不会立刻得到这个结果,而是由被调者在执行结束后主动通知(如 Callback)调用者。

2. 五种 IO 模型

IO 模型是指:用什么样的通道或者说是通信模式进行数据的传输,这很大程序上决定了程序通信的性能。

Linux 系统为我们提供五种可用的 IO 模型:阻塞式 IO 模型、非阻塞式 IO 模型、IO 多路复用模型、信号驱动 IO 模型和异步 IO 模型。

2.1 阻塞式 IO 模型

阻塞式 IO (Blocking IO):应用进程从发起 IO 系统调用,至内核返回成功标识,这整个期间是处于阻塞状态的。

2.2 非阻塞式 IO 模型

非阻塞式IO(Non-Blocking IO):应用进程可以将 Socket 设置为非阻塞,这样应用进程在发起 IO 系统调用后,会立刻返回。应用进程可以轮询的发起 IO 系统调用,直到内核返回成功标识。

2.3 IO 多路复用模型

IO 多路复用(IO Multiplexin):可以将多个应用进程的 Socket 注册到一个 Select(多路复用器)上,然后使用一个进程来监听该 Select(该操作会阻塞),Select 会监听所有注册进来的 Socket。只要有一个 Socket 的数据准备好,就会返回该Socket。再由应用进程发起 IO 系统调用,来完成数据读取。

2.4 信号驱动 IO 模型

信号驱动 IO(Signal Driven IO):可以为 Socket 开启信号驱动 IO 功能,应用进程需向内核注册一个信号处理程序,该操作并立即返回。当内核中有数据准备好,会发送一个信号给应用进程,应用进程便可以在信号处理程序中发起 IO 系统调用,来完成数据读取了。

2.5 异步 IO 模型

异步 IO(Asynchronous IO): 应用进程发起 IO 系统调用后,会立即返回。当内核中数据完全准备后,并且也复制到了用户空间,会产生一个信号来通知应用进程。

3. 总结

从上述五种 IO 模型可以看出,应用进程对内核发起 IO 系统调用后,内核会经过两个阶段来完成数据的传输:

  • 第一阶段:等待数据。即应用进程发起 IO 系统调用后,会一直等待数据;当有数据传入服务器,会将数据放入内核空间,此时数据准备好。

  • 第二阶段:将数据从内核空间复制到用户空间,并返回给应用程序成功标识。

前四种模型的第二阶段是相同的,都是处于阻塞状态,其主要区别在第一阶段。而异步 IO 模型则不同,应用进程在这两个阶段是完全不阻塞的。

IO 模型 第一阶段 第二阶段
阻塞式IO 阻塞 阻塞
非阻塞式IO 非阻塞 阻塞
IO多路程复用 阻塞(Select) 阻塞
信号驱动式IO 异步 阻塞
异步IO 异步 异步

参考资料

推荐阅读

微信搜索:码农StayUp

主页地址:https://gozhuyinglong.github.io

源码分享:https://github.com/gozhuyinglong/blog-demos

浅聊Linux的五种IO模型的更多相关文章

  1. Linux的五种IO模型及同步和异步的区别

    前置知识 缓存 I/O 缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O.在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓 ...

  2. linux的五种IO模型

    概念: 同步.异步.阻塞.非阻塞的概念 同步:所谓同步,发起一个功能调用的时候,在没有得到结果之前,该调用不返回,也就是必须一件事一件事的做,等前一件做完了,才能做下一件. 提交请求->等待服务 ...

  3. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  4. Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  5. 聊聊 Linux 中的五种 IO 模型

    本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538919&idx=1&sn=6013c451 ...

  6. Linux 下的五种 IO 模型

    概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的 ...

  7. [转载] Linux五种IO模型

      转载:http://blog.csdn.net/jay900323/article/details/18141217     Linux五种IO模型性能分析   目录(?)[-] 概念理解 Lin ...

  8. 网络通信 --> Linux 五种IO模型

    Linux 五种IO模型 聊聊Linux 五种IO模型

  9. Linux五种IO模型(同步 阻塞概念)

    Linux五种IO模型 同步和异步 这两个概念与消息的通知机制有关. 同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.比如,调用readfrom系统调用时,必须等待IO操 ...

随机推荐

  1. noip模拟10

    被打回原形了emmmmm 贴张图吧,展示一下根本不行的水平 考试经过 上来浏览一遍T1到T3,读懂题之后发现都不是很可做 T1上了想到了前缀和,往矩阵快速幂想了一下觉得不可做,半小时之后还是只会\(n ...

  2. [1.1W字] 复习: CSS 9个背景属性&6种渐变函数, 学会可以手写实现AI中强大的"任意渐变"! #Archives009

    Title/ CSS Background&Gradient完全指南 #Archives009 序: 关于 background 属性, 了解点CSS的人总会知道个大概. 但是你肯定多半还有点 ...

  3. MongoDB 数据库创建删除、表(集合) 创建删除、数据增删改查

    使用数据库.创建数据库 use student 如果真的想把这个数据库创建成功,那么必须插入一个数据. 数据库中不能直接插入数据,只能往集合(collections)中插入数据.不需要专门创建集合,只 ...

  4. QT系列

    大话QT系列:http://blog.csdn.net/houqd2012/article/category/2128295 里面有提到CTK插件系统.

  5. Python代码阅读(第2篇):数字转化成列表

    本篇阅读的代码实现了将输入的数字转化成一个列表,输入数字中的每一位按照从左到右的顺序成为列表中的一项. 本篇阅读的代码片段来自于30-seconds-of-python. digitize def d ...

  6. xv6学习笔记(5) : 锁与管道与多cpu

    xv6学习笔记(5) : 锁与管道与多cpu 1. xv6锁结构 1. xv6操作系统要求在内核临界区操作时中断必须关闭. 如果此时中断开启,那么可能会出现以下死锁情况: 进程A在内核态运行并拿下了p ...

  7. MySQL-存储引擎-1

    一.MySQL存储引擎 mysql> create table country( -> country_id smallint unsigned not null auto_increme ...

  8. Git使用教程四

    拉取线上仓库 :git pull 提醒: 在每天工作的第一件事就是先git pull拉取线上最新·的版本: 每天下班前要做的是git push,将本地代码提交到线上仓库. 有兴趣可以关注一下微信公众号

  9. JDBC分页查询及实现

    当数据过多时,一页之内是无法显示的,因此需要进行分页显示. (一)分页技术实现: 物理分页: - 在数据库执行查询时(实现分页查询),查询需要的数据--依赖数据库的SQL语句 - 在sql查询时,从数 ...

  10. 剑指 Offer 32 - I. 从上到下打印二叉树

    剑指 Offer 32 - I. 从上到下打印二叉树 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 ...