Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

理解IO模型 #6

Open
GarinZ opened this issue Feb 9, 2021 · 0 comments
Open

理解IO模型 #6

GarinZ opened this issue Feb 9, 2021 · 0 comments

Comments

@GarinZ
Copy link
Owner

GarinZ commented Feb 9, 2021

核心概念

同步/异步、阻塞/非阻塞

如何理解

同步/异步,阻塞/非阻塞这两组概念是在应用(用户进程)角度考虑的,考虑通信的双方是用户进程和内核进程。
同步/异步描述的是进程间的协作方式,强调内核提供了什么方式和用户线程通信,或者说用户进程选择使用什么内核提供的IO API进行系统调用
阻塞/非阻塞描述的是用户进程内部的处理方式,只涉及用户进程自己怎么做。

通过类比理解

去书店买书,涉及两方我和书店老板,还有一份数据就是书。

同步和异步

同步:我要买一本书,老板要求我在这等着,直到书拿过来。
异步:我要买一本书,老板说你可以先干别的。但是书准备好以后有两种方式你可以选:
方式1:好了我不告诉你,你过段时间来店里问问
方式2:好了我给你打电话
总之,这里强调的都是老板提供的方式

阻塞和非阻塞

阻塞:我下定决心,无论老板是要求我在这等着(同步)还是告诉我可以回去(异步),我就是在这死等,一直等到老板告诉我书准备好了。
非阻塞:我下定决心,无论老板是要求我在这等着(同步)还是告诉我可以回去(异步),我就是要想办法不等着。

将以上两种概念组合:
同步阻塞:我要买一本书,老板要求我在这等着,直到书拿过来。我也准备就在这等着,然后再干别的。
同步非阻塞:我要买一本书,老板要求我在这等着,直到书拿过来。我就知道会有这种情况,所以我让我小弟来,让他等着。
异步阻塞:我我要买一本书,老板说你可以回去了。我也准备就在这等着。
异步非阻塞:我我要买一本书,老板说你可以先干别的,但这时候我有两种选择:
选择方式一:我当人肉复读机,过段时间就来问老板“书准备好了没有”
选择方式二:我先做别的了,等着老板告诉我结果

从计算机角度来看

同步和异步

同步:用户进程/线程要通过IO获取数据,使用内核提供的阻塞IO,调用这个API会挂起进程/线程。但是当执行结束后会直接返回结果。

异步:用户进程/线程要通过IO获取数据,内核提供了多种IO方式:非阻塞IO和IO复用(注意这里的非阻塞和异步是同一个含义)
1)非阻塞IO(Non-Blocking IO):这是内核实际提供的API,虽然立刻返回文件描述符,但需要用户进程主动查询数据ready情况。

2)IO多路复用(I/O multiplexing):可以一口气监听多个文件描述符的准备情况,这里又分使用的是select还是epoll。但无论选哪一个,能拿到的只是文件描述符的可读状态,用户进程拿到了可读的文件描述符,仍需要一次系统调用将数据拷贝到用户空间,而这一步是阻塞的。
2.1)select:被监听的文件描述符集合中有ready的了就调用回调函数,但需要自己遍历文件描述符集合
2.2)epoll:被监听的文件描述符集合中有ready的了就调用回调函数,并且直接告诉你那个文件描述符ready并且数据已经帮你读好了,不用自己遍历。

3)信号驱动IO(signal driven I/O):不再监听文件描述符,而注册信号处理程序数据ready后内核直接调用信号处理程序,但信号处理程序内被仍需要进行系统调用将数据从内核空间拷贝到用户空间,期间阻塞用户进程。

4)异步IO(asyncrhonized I/O):也是先注册信号处理程序,但是这次会由内核直接完成从内核空间到用户空间的拷贝,减少了一次系统调用。用户的信号处理程序可以直接拿到可直接使用的数据。

阻塞和非阻塞:实际开发中阻塞和非阻塞无法脱离同步/异步API的选择单独讨论,因此我们还得结合起来看

概念组合

  • 同步阻塞:使用内核提供的阻塞IO,调用期间当前进程/线程被挂起,不再参与调度
  • 同步非阻塞:创建子线程,在子线程内使用内核提供的阻塞IO,主线程可以继续执行
  • 异步阻塞:使用上述任意异步IO,用户线程使用wait()sleep()之类的方法主动挂起
  • 异步非阻塞:1)使用非阻塞IO,则定期轮询 2)使用IO多路复用、信号驱动IO、异步IO可以继续执行其他任务

总结

所以,这个两组概念其实是在帮我们约束两个方面的技术选型:
1)同步/异步是让我们选择用户进程使用哪种IO API来完成系统调用层面的IO
2)阻塞/非阻塞是应用在选定IO API的前提下,决定以什么方式调用IO API以及调用之后该做什么

参考文章

萧萧的回答 - 怎样理解阻塞非阻塞与同步异步的区别?
Shihui wang的回答 - 怎样理解阻塞非阻塞与同步异步的区别?
Unix网络编程的5种I/O模型

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant