数据搬运工大家好,我是CPU一号车间的阿Q,好久不见。还记得上次说我们厂用DMA技术(慢得受不了!CPU又占硬盘网卡了!),之后终于解放了,再也不用在网卡、硬盘和内存之间跑来跑去。数据。前段时间,我去二车间看望虎子,发现他正忙得满头大汗。“兄弟,你接到什么任务了?你看,我帮你。”虎子见我来了,擦了擦额头的汗说:“我在搬资料,刚搬完A批,累死了。”我有些纳闷:“我们现在不是有DMA技术了吗,找个外购的DMA控制器来承载,你怎么还自己做?”“DMA用于I/O外部设备和内存,我现在的任务是在内存之间拷贝拷贝,这个DMAC帮不上什么忙,只好自己拷贝了。”我抿了抿嘴,“是的,我希望我不要接受这种任务。”“我暂时不和你说话,我还有工作要做”,胡子起身工作又在他屁股热了之前,我也起身准备回去。“可恶!怎么又要复制这批数据!”,刚走了两步,就听到虎子抱怨道。我转身问:怎么了?“我只是将这些数据从内核地址空间复制到用户态地址空间。搬回内核地址空间对我来说太麻烦了!”我拍了拍他的肩膀说:“哎,没办法,我们只是打工,挑挑拣拣哪一轮吧,加油!”我一边说一边给他打气,心里暗暗祈祷不要给我安排这种工作,不管是累还是技术。事出有因,回到一号车间没多久,我也遇到了这种事。俗话说,真怕出事。刚开始还能忍,时间久了就抑制不住心中的不满,直到落到自己身上时,我才体会到痛苦。数据四份第二天和虎子约好了,把这件事汇报给操作系统的内存管理部门。内存管理部门居然踢球了,说这事他们管不了,让我们找I/O部门,可是没办法,我们就来I/O部门反映这事了。听了我们的抱怨,I/O部门的人很是无奈:“两个,我们真的不是故意逗你们的,之前真的没办法要求你们两次移动数据,这是什么上面的应用程序应该写。他们需要读取硬盘上的文件,然后通过网卡发送出去。读和写不需要移动两次吗?"File.read(file,buf,len);Socket.send(socket,buf,len);"硬盘?网卡?这,这,这,我们不是有DMA技术吗,只是解决了跟他们的数据传输,干嘛让我们在内存之间copy啊copy啊?”,我问道。对方看出了我们的疑惑,在旁边的白板上画了一张图:“你看,数据是从硬盘到网卡的。因为有应用程序的参与,需要读取用户空间的缓冲区,然后发送出去,这样一共有四次数据发送。其中,从硬盘到内核空间,从内核空间到网卡,DMAC都能帮你扛过去。但是,用户空间和内核空间之间剩下的两个往返副本必须由您处理。”涂郁闷的说道。但是我不想放弃,我想找出这张图可以优化和改进的地方。“能不能让数据不去应用程序,在内核空间拷贝一次,我们就可以少动一次?”,我提出了一个问题。“怎么可能?他不看,以后怎么发?”不不不不。”I/O部门的人连连摇头。“还是可以发送的,你看是这样的……反正数据最后是从内核空间发送到网卡的,只是数据到用户空间暂时还省了点。”废物”,我换了他画的图,不肯放弃解释。对方像是被我的话惊醒了,眼睛左右转动,思索了很久。过了一会,他回道:“还是不行,万一有人要修改或解密读取的文件数据,你还是得读取他的用户空间缓冲区。并说道:“那我们就认清这种情况吧,反正以我的经验来看,你说的这种情况并不多。大多数情况下,数据从内核到用户空间都是原封不动的,再从用户空间回到内核。”I/O部门的人也没有再多辩解,点头同意,说我们会把我们的意见汇报给Linux帝国高层讨论后再做决定,先回去等消息。零拷贝技术。然而工作太忙,操作系统一直没有消息。慢慢的,直到几天前,我们才忘记这件事……”阿Q,你听说过吗,最近Linux帝国成立了一家新公司,居然可以绕过我们的CPU,把网卡的数据写入硬盘”虎子急忙来找我。“不可能,按照我们之前的计划,至少要复制一次。”“完全没有必要,他们号称是零拷贝技术。”我们赶紧放下手中的活儿,去探个究竟。原来Linux帝国最近推出了一个新的API,叫做sendfilesize_tsendfile(intout_fd,intin_fd,off_t*offset,size_tcount);只需要指定打开文件的描述符和发送的网络接口描述符,就可以直接通过网络发送文件。发出。我们又来到了操作系统I/O部门,对方一看是我们,热情的接待了我们。“你们来得正是时候,我还没来得及告诉你们呢。你们上次提出的想法很好,帝国高层也很重视,我一反应过来,立即采纳你的意见,你可能已经知道了,新的API是应用程序使用的,白白节省了数据去用户空间的成本,刚上线的时候很火爆,不得不感谢大家”“所以这就是我最近说的如何移动数据的工作减少了很多。但是你是如何实现零拷贝的?”I/O部门的人看了我们一眼,得意地笑道:“帝国高层在讨论你们的方案的时候,觉得还可以进一步优化,直接给出数据缓冲区的地址和长度从硬盘读取到网络套接字描述符,不需要再移动数据,彻底解放你,所以叫零拷贝!”我们都点头称赞。“还没完呢!我们Linux帝国还把这项技术扩展到文件数据复制上,还增加了一个API:splice,以后文件复制也能减轻你的负担。”ssize_tsplice(intfd_in,loff_t*off_in,intfd_out,loff_t*off_out,size_tlen,unsignedintflags);回去后,我们把这个消息通知了全厂,大家都很高兴。原来各作坊苦了半天。
