0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

网络IO模型:阻塞与非阻塞

麦辣鸡腿堡 来源:盼盼编程 作者:盼盼编程 2023-10-08 17:16 次阅读

阻塞 IO 模型

Linux ,默认情况下所有的 socket 都是阻塞的,一个典型的读操作流程如图所示。

阻塞和非阻塞的概念描述的是用户线程调用内核 IO 操作的方式:阻塞是指 IO 操作需要彻底完成后才返回到用户空间;而非阻塞是指 IO操作被调用后立即返回给用户一个状态值,不需要等到 IO 操作彻底完成。

当应用进程调用了 recvfrom 这个系统调用后,系统内核就开始了 IO 的第一个阶段 :准备数据。

对于网络 IO 来说,很多时候数据在一开始还没到达时,系统内核就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。

当系统内核一直等到数据准备好了,它就会将数据从系统内核中拷贝到用户内存中,然后系统内核返回结果,用户进程才解除阻塞的状态,重新运行起来。所以,阻塞IO 模型的特点就是 IO 执行的两个阶段都被阻塞了。

大部分的 socke接口都是阻塞型的。所谓阻塞型接口是指系统调用时却不返回调用结果,并让当前线程一直处于阻塞状态,只有当该系统调用获得结果或者超时出错时才返回结果。

实际上,除非特别指定,几乎所有的 IO 接口都阻塞型的。这给网络编程带来了一个很大的问题,如在调用 send的同时,线程处于阻塞状态,则在此期间,线程将无法执行任何运算或响应任何网络请求。

非阻塞 IO 模型

在Linux 下,可以通过设置 socket IO 变为非阻塞状态。当一个非阻塞的 socket执行 read 操作时,流程如图:

图片

当用户进程发出 read 操作时,如果内核中的数据还没有准备好,那么它并不会 block 用户进程,而是立刻返回一个错误。

从用户进程角度讲,它发起 read 操作后,并不需要等待,而是马上就得到了一个结果当用户进程判断结果是一个错误时,它就知道数据还没有准备好,于是它可以再次发送 read 操作。

一旦内核中的数据准备好了,并且又再次收到了用户进程的系统调用,那么它马上就将数据复制到了用户内存中,然后返回正确的返回值。

所以,在非阻塞式 IO 中,用户进程其实需要不断地主动询问 kernel数据是否准备好。非阻塞的接口相比于阻塞型接口的显著差异在于被调用之后立即返回,使用如下的函数可以将某句柄归设为非阻塞状态:fcntl( fd , F_SETFL, O_NONBLOCK);

在非阻塞状态下,recv 接口在被调用后立即返回,返回值代表了不同的含义,如下所述。

recv 返回值大于 0,表示接收数据完毕,返回值即是接收到的字节数。

recv 返回 0,表示连接已经正常断开。

recv 返回 -1 ,且 errno 等于 EAGAIN ,表示 recv 操作还没执行完成。

recv 返回 -1,且 errno 不等于 EAGAIN ,表示 recv 操作遇到系统错误 errno。

可以看到服务器线程可以通过循环调用 recv 接口,可以在单个线程内实现对所有连接的数据接收。但是上述模型绝不被推荐,因为循环调用 recv将大幅度占用 CPU 使用率。

此外,在这个方案 recv 更多的是起到检测“操作是否完成”的作用,实际操作系统提供了更为高效的检测“操作是否完成”作用的接口,例如 select多路复用模式,可以次检测多个连接是存活跃。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • IO
    IO
    +关注

    关注

    0

    文章

    397

    浏览量

    38516
  • 内核
    +关注

    关注

    3

    文章

    1309

    浏览量

    39850
  • Linux
    +关注

    关注

    87

    文章

    10991

    浏览量

    206742
  • 网络
    +关注

    关注

    14

    文章

    7251

    浏览量

    87445
收藏 人收藏

    评论

    相关推荐

    Verilog阻塞阻塞原理分析

    Verilog阻塞阻塞原理分析在Verilog语言最难弄明白的结构中“阻塞赋值”要算一个。甚至是一些很有经验的工程师也不完全明白“
    发表于 11-23 12:02

    linux串口通信阻塞阻塞问题。

    一般情况下串口通信中read()函数都是阻塞的。当然也可以通过设置文件等方法把串口设为阻塞的。这里就有一个问题,当串口设置为阻塞状况下,如果读不到数据程序应该挂起。这种所谓的读不到数
    发表于 07-14 15:57

    【分享】Verilog中阻塞阻塞语句

    同了在第一个clk上升沿到来时,由于b的值未知,赋给c之后,c也为未知值;紧接着,把a的值给b,由于a的值已经给出,所以,结束之后,a、b的值相同,c为x。综合之后,生成两级移位寄存器。 关于阻塞
    发表于 11-03 20:26

    fpga基础篇(一):阻塞阻塞赋值

    `阻塞阻塞赋值首先从名字上理解,阻塞赋值即赋值没完成,后边的语句将无法执行,阻塞刚好与其相
    发表于 04-05 09:53

    Verilog中阻塞赋值和阻塞赋值的正确使用

    [table][tr][td] Verilog中有两种为变量赋值的方法。一种叫做连续赋值,另一种叫做过程赋值。过程赋值又分为阻塞赋值和阻塞赋值。阻塞性赋值使用“=”为变量赋值,在赋值
    发表于 07-03 03:06

    阻塞(=)与阻塞(<=)介绍

    语句的执行,延迟后才执行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。 阻塞赋值操作符用小于等于号(即
    发表于 07-03 10:23

    阻塞(=)与阻塞(<=)介绍

    语句的执行,延迟后才执行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。 阻塞赋值操作符用小于等于号(即
    发表于 07-09 05:08

    【工程源码】 阻塞赋值与阻塞赋值原理分析

    本文和设计代码由FPGA爱好者小梅哥编写,未经作者许可,本文仅允许网络论坛复制转载,且转载时请标明原作者。阻塞赋值,操作符为“=”,“阻塞”是指在进程语句(initial和always)中,当前
    发表于 02-24 20:09

    【技巧分享】FPGA至简设计-阻塞赋值与阻塞赋值

    阻塞阻塞作者:小黑同学一、 概述1、阻塞赋值对应的电路往往与触发沿没有关系,只与电平的变化有关系。阻塞赋值符号“=”。2、
    发表于 04-24 14:49

    同步与异步,阻塞阻塞的区别是什么

    同步与异步,阻塞阻塞的区别
    发表于 01-26 06:12

    怎么使用Select实现阻塞网络编程?

    使用Select实现阻塞网络编程
    发表于 03-30 07:34

    阻塞阻塞赋值的区别是什么?

    本文通过Verilog事件处理机制,详细讨论了阻塞阻塞赋值的区别、联系及其应用示例。
    发表于 05-10 06:59

    《Linux设备驱动开发详解》第8章、Linux设备驱动中的阻塞与非阻塞IO

    《Linux设备驱动开发详解》第8章、Linux设备驱动中的阻塞与非阻塞IO
    发表于 10-27 11:35 9次下载
    《Linux设备驱动开发详解》第8章、Linux设备驱动中的<b class='flag-5'>阻塞</b>与非<b class='flag-5'>阻塞</b><b class='flag-5'>IO</b>

    深入分析同步阻塞网络IO的内部实现详解

    网络开发模型中,有一种非常易于开发同学使用的方式,那就是同步阻塞网络 IO(在 Java 中习惯叫 BIO)。
    的头像 发表于 04-03 14:10 1801次阅读
    深入分析同步<b class='flag-5'>阻塞</b><b class='flag-5'>网络</b><b class='flag-5'>IO</b>的内部实现详解

    时序逻辑中的阻塞和非阻塞

    Verilog HDL的赋值语句分为阻塞赋值和非阻塞赋值两种。阻塞赋值是指在当前赋值完成前阻塞其他类型的赋值任务,阻塞赋值由=来完成;非
    的头像 发表于 03-15 13:53 2596次阅读