IO会一直占用CPU吗?

IO会一直占用CPU吗?

这是一个很好的关于并发/并行系统的问题。简单回答就是:IO所需要的CPU资源非常少。大部分工作是分派给DMA(Direct Memory Access)直接内存存取完成的。先不谈传统的5大IO模型,先说说并发(Concurrencey)。一个非常不严谨的解释就是同时做A和B两件事。先做一会儿进程A,然后上下文切换,再做一会儿B。过一会儿在切回来继续做A。因此给我们造成一个假象,我们同时在做A和B两件事。这就是著名的进程模型。这看上去很炫酷,但实际上并没有任何卵用。因为A,B两件事你都得做完不是?不论你是做完A再做B还是来回切换,花得时间应该是一样的。甚至还要更多,因为还要考虑到上下文切换的开销。

如果计算机内部不止CPU一个部件在工作呢?如果A这件事CPU可以分派给其他部件帮它完成呢?情况是不是就完全不一样了?
系统IO正好是这样一个完美的例子。对于磁盘IO,真实发生的场景可能是这样的:

当然我们也可以到网上下载苍老师的作品,这就是网络IO。但情况基本是一样的,CPU童鞋在等小电影的过程中,打了一局撸啊撸。所以,正因为这样派发任务,通讯,等待的过程,并发系统才彰显出它的意义。当然实际过程可能比这个复杂一万倍。比如CPU是不会直接和硬盘对话的,他们之间有个中间人,叫DMA(Direct Memory Access)芯片

这个过程,对应下图(图源:《UNIX网络编程》),看到application这一列时间线了吗?aio_read操作之后,都是空白,CPU就不管了,可以做其他事去了。

假设原先读取文件CPU需要傻等50纳秒。现在尽管两次上下文切换要各消耗5纳秒。CPU还是赚了40纳秒时间片。一看上面这张图就知道,刚才讲的是传统5大IO模型中的“异步IO”的大致过程。计算机硬件上使用DMA来访问磁盘等IO,也就是请求发出后,CPU就不再管了,直到DMA处理器完成任务,再通过中断告诉CPU完成了。所以,单独的一个IO时间,对CPU的占用是很少的,阻塞了就更不会占用CPU了,单线程环境下会导致程序都不继续运行了,在多线程环境下,CPU会把时间交给其它线程和进程了。

那么问题来了,这个IO操作会阻塞多久?CPU什么时候会切回到原线程并继续执行?
这里涉及到上文提到的IO通信模型。虽然IO不会占用大量的CPU时间,但是非常频繁的IO还是会非常浪费CPU时间的,所以面对大量IO的任务,有时候是需要算法来合并IO,或者通过cache来缓解IO压力的,使用良好的通信模型也会大大提高我们的代码的执行效率。

posted @ 2020-08-10 15:40  晓桦  阅读(1264)  评论(0编辑  收藏  举报