阻塞与非阻塞IO step by step
谈到IO,阻塞、非阻塞,异步、同步是绕不开的话题。说实话,我也没搞清楚,网上查了许多资料,大家众说纷纭,一种比较靠谱的说法是:”在处理 IO 的时候,阻塞和非阻塞都是同步 IO,使用使用了特殊的API才是异步IO“。知乎的回答相对来说可信度高点,大家姑且可以先看着:
http://www.zhihu.com/question/19732473
这些资料大多说理,我还是想通过一些例子,以我们看到到摸得着的方式,慢慢搞懂阻塞、非阻塞以及异步同步间的关系。所以这一系列将是我的读书笔记,因为我也摸着石头过河,等过完河我再整理IO这一个系列的文章。
阻塞和非阻塞
阻塞与非阻塞是个概念,概念背后肯定有很多内容嘛,我们一一展开。首先,主语是操作系统(OS),宾语是进程,也就是说,阻不阻塞都是针对进程的;我们知道阻塞与不阻塞是针对于同一问题的两种处理方式,那么这个问题又是什么呢?答,是当我进程要读数据时,数据还没准备好,在这种情况下操作系统的策略。用户态进程想走下去,需要读取硬件上收集的数据,用户态到硬件间的距离,隔着一个操作系统,操作系统此时向用户态提供了两种解决方案:①阻塞,进程在等待队列上睡觉,到时叫醒你;②非阻塞,返回给你个码字,告诉你数据没准备好,你可能还要再来问一遍。
来点接地气的。下面这个程序很简单,不断从标准输入里读出数据,然后显示。
1 2 3 4 5 | 33 while (1){ 37 ntowrite = read(0, buf, sizeof (buf)); 39 printf ( "ntowrite:%d\n" , ntowrite); 40 sleep(2); 42 }; |
默认情况下,io是阻塞的,所以你会发现,程序会傻傻地卡在那里,等着输入:
hon@hon:~/f2fs/share_aarch64/filemap$ ./block_test
但是把上面的程序作如下修改,即通过fctnl将对stdin的读操作变成非阻塞的,结果就会变得大不一样。
25 flag = fcntl(0, F_GETFL, 0); 26 flag |= O_NONBLOCK; 27 error = fcntl(0, F_SETFL, flag); 28 if (error < 0) 29 printf("std stdion to non-block fails\n"); 30 while(1){ 34 ntowrite = read(0, buf, sizeof(buf)); 36 printf("ntowrite:%d\n", ntowrite); 37 sleep(2); 38 39 };
这次的结果是,程序不再傻等了,-1 就是操作系统给你的信息了:当前并没什么卵数据。
hon@hon:~/f2fs/share_aarch64/filemap$ ./block_test ntowrite:-1 ntowrite:-1 ntowrite:-1 ntowrite:-1 ntowrite:-1 ntowrite:-1
.....
上面就是不是对阻塞非阻塞有了个感性的认识呢?阻塞时,程序在 read 调用处傻傻等着,因为操作系统让你睡眠了;非阻塞时,操作系统不会让你等,有数据就返回数据,没数据就直白告诉你,但是总会返回。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!