在Linux系统中,磁盘与主存之间的数据传输效率,直接决定了整个系统的响应速度。你可能没意识到,当你打开一个文件、下载一份资料时,背后正运行着一套精密的传输机制。今天我们就聊聊支撑这一切的3种核心传输方式——轮询、I/O中断和DMA传输,看看它们是如何一步步让CPU从“忙到停不下来”变成“高效摸鱼”的。磁盘与主存的数据传输,本质是“把数据从磁盘搬到内存”的过程,而不同机制的核心区别,就在于CPU在这个过程中需要付出多少精力:
轮询方式:最“原始”的方式,CPU会进入死循环,不停检测I/O端口的状态——“数据准备好了吗?准备好了吗?”,全程无法做其他事,CPU利用率极低且浪费严重。
I/O中断方式:CPU不用一直盯着了,但数据到达时,磁盘会主动“叫醒”CPU,让CPU亲自负责数据传输。虽然比轮询进步,但每次传输都要打断CPU的工作,频繁切换状态。
DMA传输方式:引入了“专属搬运工”——DMA控制器,让它直接负责数据传输,CPU只需要在开始和结束时做简单的“交接工作”,全程可以专注做其他计算任务,效率大幅提升。
在DMA技术出现之前,I/O中断是主流的传输方式。简单说,就是“磁盘喊CPU,CPU来干活”,整个过程CPU全程参与,步骤清晰但繁琐。
用户进程要读取磁盘数据,必须通过系统调用让CPU介入,而且会涉及“用户态”和“内核态”的切换。通俗理解,这就像普通员工(用户进程)要拿仓库里的东西(磁盘数据),必须找管理层(CPU)审批,审批过程中员工只能等着。
用户进程向CPU发起read系统调用,主动从“用户态”切换到“内核态”,然后进入阻塞状态,乖乖等数据返回。
CPU接收到指令后,直接向磁盘发起I/O请求,让磁盘先把数据放到自己的缓冲区(磁盘控制器缓冲区)里。
等磁盘把数据准备好,就会主动向CPU发“中断请求”,相当于喊“CPU,数据准备好了,快来拿!”
CPU收到中断后,暂停手头的工作,把磁盘缓冲区里的数据先拷贝到内核缓冲区,再从内核缓冲区拷贝到用户缓冲区(相当于CPU亲自把数据从仓库门口搬到员工桌上)。
数据拷贝完成后,用户进程从“内核态”切回“用户态”,解除阻塞,等待CPU下一次调度执行。
这里的关键问题是:每次I/O操作都要打断CPU,而且要做两次数据拷贝(磁盘→内核→用户),还伴随着多次上下文切换。如果系统中有大量I/O请求,CPU就会被这些“杂活”占满,根本没精力做核心的计算任务。
为了解决I/O中断的痛点,DMA(直接内存存取,Direct Memory Access)技术应运而生。它的核心思路很简单:找一个“专属搬运工”(DMA控制器),让它负责数据传输,CPU只做“开头交代任务、结尾验收成果”的工作。
现在大部分硬件(磁盘控制器、网卡、显卡等)都支持DMA技术,有了这个“搬运工”,数据传输就能绕开CPU的全程调度,让CPU和I/O操作并行进行,系统效率直接翻倍。
同样以读取磁盘数据为例,DMA传输的流程是这样的:
用户进程发起read系统调用,从用户态切换到内核态,进入阻塞状态等待数据。这一步和I/O中断是一样的。
CPU接收到指令后,不再直接对接磁盘,而是向DMA控制器下发调度指令,相当于告诉“搬运工”:“去把磁盘里的数据搬到内存里,完事叫我”。
DMA控制器接收到任务后,主动向磁盘发起I/O请求,让磁盘把数据放到磁盘控制器缓冲区。这个过程中,CPU完全不用参与,可以专心做其他计算任务。
磁盘把数据准备好后,通知DMA控制器,DMA控制器直接把数据从磁盘缓冲区拷贝到内核缓冲区(“搬运工”亲自干活,不用麻烦CPU)。
数据传输完成后,DMA控制器向CPU发送“完成信号”(中断请求),CPU收到后,只需要做最后的收尾工作——把内核缓冲区的数据拷贝到用户缓冲区。
用户进程从内核态切回用户态,解除阻塞,等待CPU调度执行。
从轮询到I/O中断,再到DMA传输,本质是一场“解放CPU”的进化:
理解这三种机制,不仅能帮我们搞懂Linux系统的I/O底层逻辑,也能明白为什么有些程序在大量读写磁盘时,CPU占用率却不高——这背后正是DMA技术在默默发力。
其实,DMA传输虽然解放了CPU,但数据传输过程中仍存在两次拷贝的“隐形消耗”。而后续我们要讲的「零拷贝原理」,就是要彻底解决这个拷贝痛点,让数据传输效率再上一个台阶!下一篇推文,我们就来深挖零拷贝的核心逻辑,看看它是如何实现“数据不落地”的高效传输的,敬请期待~
最后,如果觉得这篇内容对你有帮助,期待你的点赞、在看、转发,让更多人一起学习~ 若有疑问,欢迎在评论区留言~