赞
踩
并发,顾名思义就是多个程序一起运行。运行在哪里呢?当然是cpu
所以并发就是多个程序一起运行在cpu上咯?
no no no!就单个cpu而言,一次只能处理一个程序,之所以能够看起来「一起运行」,是因为操作系统采用了分时系统,什么时间片,调度算法啦,让程序交替式的在cpu上运行,看起来好像是一起运行一样(这里不展开了,后面再更新给大家)
所以这就是并发的全部意义吗?就是多个程序通过操作系统的调度交替运行,看起来像一起运行,所以称为并发?
当然不是,之所以称为并发编程,是因为它们有真正同时运行的地方。
回顾一下操作系统的基础知识。我们知道,操作系统是采用虚拟存储的,它的核心是内核,为了保护内核的安全,操作系统把虚拟空间划分成两部分,一部分是内核空间,一部分是用户空间,就像星空战舰上的指挥室一样。
这时候聪明的的你肯定就会发现一个问题
cpu运算的结果是放在内核空间的,而我们读取结果却是在用户空间,这就有一个数据从内核空间到用户空间的过程
没错,从操作系统层看程序运行时的数据流的话,是有 「等待数据 --- 数据拷贝到内核空间 --- cpu运算 --- 数据从内核空间拷贝到用户空间」 这几个过程的
程序运行时的数据流动过程
并发,就发生在这几个过程中。
来一张经典的示意图
中间的部分就是并发的部分,只要保证cpu运算的过程是串行的,其他过程都可以并发执行。
我们把数据从「等待」到「拷贝到用户空间」称作一次 IO操作
其中,「等待数据 --- 数据拷贝到内核空间 --- cpu运算」叫做 数据准备阶段,「数据从内核空间拷贝到用户空间」叫做 数据拷贝阶段
没有实际应用的知识是没有灵魂的,同样,没有被面试官问起的知识点都是孤独的..
当我们兴高采烈地聊到这里时,面试官会笑眯眯的问你
好的,你来讲一下linux中有哪些网络io模式吧?
好吧算你狠。
Linux中有五种网络io模式,分别是
其中因为 信号驱动 I/O 不常用,所以一般只要了解其他四种 I/O 模式
当我们掰着指头好不容易数出这五种模式时,刚才还昏昏欲睡的面试官突然眼睛一亮,皮笑肉不笑地对你说
不错嘛,那你来说说 阻塞/非阻塞 IO 和同步/异步 IO的区别吧?
搞我是吧,但既然人家问,咱也只能准备。要分清这四个概念,就要牢牢记住之前数据流动的过程
(再放一遍)
用户空间因为不能直接访问内核空间,当他想要结果时需要发起一个 read调用
但数据的准备和计算是需要一个过程的。比如我们进行网络请求的时,数据还没有返回,这个过程需要等待,当数据返回后被拷贝到内核空间,经过一系列运算,最终拷贝到用户空间。
进程发起调用后就一直等待,也就是阻塞状态。
等到数据拷贝完成后,进程还不能运行,需要内核给一个 ok 的信号,告诉进程数据已经拷贝到你那里了,用户进程这才解除阻塞状态,愉快的运行起来。
所以很明显,阻塞 I/O的特点是内核返回数据拷贝完成的信号之前,进程一直被阻塞。也就是说阻塞其实包括两个阶段,一个是等待数据准备,一个是数据从内核空间拷贝到用户空间
ok,理解了阻塞 I/O 的调用过程后,接下来的I/O模式就很简单了
和「阻塞 I/O」不同的是。「非阻塞 I/O」的进程发起一个read调用时,如果内核的数据还没有准备好,它就会立刻返回一个error信号。
从用户进程的角度讲,它发起一个read操作后,并不需要等待就马上得到了一个结果,当用户进程判断结果是一个error时,它知道数据还没有准备好,于是再次发送read调用,一遍又一遍地询问。
当内核运算完毕准备好数据,并且再次收到用户进程的调用时,它就马上把数据拷贝到用户空间里,然后返回ok信号
所以「非阻塞 I/O」的特点是,用户进程不断询问内核,数据好了没有
「I/O 多路复用」实际上是「阻塞 I/O」的变种。
select,poll,epoll都是「I/O 多路复用」的机制,它的好处在于单个进程就可以同时处理多个网络连接的IO
单个进程处理多个网络连接??!
没错,比如select方法。用户进程先调用select方法,select干了两件事,一个是管理多个负责网络连接的socket,另一个是让内核监视socket的状态
当内核接收到socket返回的数据并运算完成后,select方法就会返回,这时用户进程再发起read调用,把数据从内核空间拷贝到用户空间里
需要注意的是,socket本身是非阻塞的,但整个用户进程是阻塞的。
这种阻塞包括两个阶段,一个是发起select方法等待socket返回数据时阻塞,另一个是等待数据从内核控件拷贝到用户空间时阻塞,从这就可以看出和「阻塞 I/O」其实是一样的
所以,「I/O 多路复用」的特点是一个进程可以同时等待多个信号,任意一个信号就绪时发起系统调用
终于到最后一个啦,加油加油!
区别于上面几种I/O模式,「异步 I/O」是没有阻塞的
用户进程发起read调用之后,立刻就可以开始去做其它的事。内核会立刻返回,所以不会对用户进程产生任何阻塞。
当内核数据计算完成后,它会自动把数据拷贝到用户空间,然后再给用户进程发送一个信号,告诉它read调用完成了。所以用户进程并不是在收到ok信号后拷贝数据,数据拷贝阶段也不会阻塞
所以「异步 I/O」的特点是,用户进程不需要等待内核返回的信号,一直运行
终于介绍完啦
总结一下
阻塞io和非阻塞io的区别是
内核准备数据时有没有立即返回。
阻塞io只有在内核准备好数据后才返回,而非阻塞io在准备过程中一直返回。
同步io和异步io的区别
同步io会阻塞进程,异步io不会阻塞进程
所以其实「阻塞 I/O」,「非阻塞 I/O」和「I/O 多路复用」都是同步I/O
前面不够细心的小伙伴可能会问了
为什么「非阻塞 I/O」是同步I/O呢?
仔细看「非阻塞 I/O」的流程图
当内核的数据准备好后,用户进程再次询问时,数据开始从内核空间拷贝到用户空间。这个过程中用户进程是阻塞的,只有当拷贝完成,内核返回完成信号,进程才会继续运行。
所以,不管是「阻塞 I/O」还是「非阻塞 I/O」都是会发生阻塞
不同的是,「阻塞 I/O」在数据准备阶段和从内核空间拷贝到用户空间阶段都会阻塞,「非阻塞 I/O」只有在拷贝阶段会阻塞。
作者:方木Rudy
链接:https://juejin.im/post/5ece31e6e51d4578a51f7bf4
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。