1. 程式人生 > >CPU:別再拿我當搬磚工了!

CPU:別再拿我當搬磚工了!

資料搬運工

Hi,我是CPU一號車間的阿Q,有段日子沒見面了。

還記得上回說到咱們廠裡用上了DMA技術(太慢不能忍!CPU又拿硬碟和網絡卡開刀了!)之後,我們總算解放了,再也不用奔波於網絡卡、硬碟與記憶體之間搬運資料了。

 

 

前段時間,我到二號車間虎子那裡去串門,發現他正忙的滿頭大汗。

“老哥,你這是接到什麼任務了?看把你給你忙的”

虎子一看我過來,擦了擦頭上的汗說到:“我這是在搬運資料啊,剛剛搬完一批,累死我了”

我有些疑惑:“咱們現在不是有DMA技術了嗎,找外包DMA控制器搬運啊,你幹嘛還親自上陣?”

“DMA是用於I/O外部裝置與記憶體之間搬運資料,我現在的任務是記憶體之間的複製拷貝工作,這DMAC也幫不上什麼忙啊,還不得我親自動手複製。”

 

 

我癟了癟嘴,“也是,但願我不要接到這種任務”

“先不跟你聊了,又有活要乾了”,虎子屁股還沒坐熱,又起身去忙了,我也起身準備回去。

“我靠!怎麼又要拷貝這批資料!”,我剛走兩步,就聽到虎子的吐槽。

我回過頭去問到:“咋了這是?”

“我剛才才把這份資料從核心地址空間往使用者態地址空間拷貝了一次,這還沒喘口氣,又讓我再搬一次從使用者態再搬回核心地址空間,太折騰我了吧!”

我拍了拍他的肩膀說到:“嗨,這沒辦法,咱們就是打工的,哪輪得到咱們挑挑揀揀啊,加油吧!”

我一邊給他打氣,一邊暗自祈禱別給我安排這種活,又累有沒有技術含量。

天有不測風雲,回到一號車間沒多久,我也攤上這種事了。老話說得好,真是怕什麼來什麼。

一開始我還能忍著,時間一久我就抑制不住心裡的不滿了,還真是落在自己身上才知道痛。

資料的四次拷貝

第二天,我約上虎子去找作業系統記憶體管理部門反應這事。

記憶體管理部門居然踢皮球,說這事不歸他們管,讓我們找I/O部門,沒辦法,我們又來到I/O部門反應這事。

 

 

I/O部門的人聽完我們的抱怨,也很無奈:“兩位,實在不是我們故意戲耍你們。之前讓你們兩次搬運資料實在沒有辦法,這是上邊的應用程式要這樣寫的。他們要把硬碟上的檔案讀取出來,然後再通過網絡卡傳送出去。這一讀一寫的不就要搬兩次嗎?”

File.read(file, buf, len);
Socket.send(socket, buf, len);

“硬碟?網絡卡?這,這,這我們不是有了DMA技術了嗎,正好解決了和他們的資料傳輸,幹嘛還另外讓我們再在記憶體之間複製來複制去呢?”,我問到。

對方看出了我們的疑惑,在旁邊的白板上畫了一張圖:

 

 

“你們看,資料從硬碟最終到網絡卡,因為有應用程式的參與,他們需要先讀到他們在使用者空間的快取區,再發送出去,這樣就總共有四次資料的傳輸。其中從硬碟到核心空間和從核心空間到網絡卡這兩個環節,DMAC可以幫你們搬運。不過剩下兩次的使用者空間和核心空間的來回拷貝,這還得靠你們來搬運下啊”

“原來是這樣,唉,看來是沒辦法避免了,咱先回去吧”,虎子看完圖垂頭喪氣的說到。

我卻不願放棄,想在這圖中找出可以優化改進的地方。

 

 

“能不能讓資料不要去應用程式那裡,直接在核心空間複製一次就好,我們就可以少搬運一次了?”,我丟擲了一個問題。

“那怎麼可能呢,他不讀上去,後面怎麼發出去呢?不行不行”,I/O部門的人連連搖頭。

“還是可以發啊,你看像這樣···反正最後也是把資料從核心空間交給網絡卡發,只是免去了資料去使用者空間白晃一圈的浪費”,我把他畫的圖改了一下,不肯放棄解釋到。

 

 

對方被我的話點醒了一般,眼珠左右轉動,反覆思考。

片刻之後,回到:“還是不行,萬一人家要對讀取的檔案資料進行修改,或者解密,那還是得讀到他的使用者空間快取區才行”

我想了一下,這似乎沒辦法避免,說到:“那這種情況咱們就認了,反正以我的經驗來看,你說的這種情況不多。大部分情況下都是資料原封不動的從核心到使用者空間,又從使用者空間回到核心。”

I/O部門的人再也沒有什麼說辭,點了點頭答應了下來,說把我們的意見彙報到Linux帝國高層討論後才能做決定。我們就先回去等訊息了。

零拷貝技術

不過後來工作太忙,遲遲沒有作業系統那邊的訊息,慢慢的我們就把這事給淡忘了,直到前幾天······

“阿Q,聽說了嗎,最近Linux帝國新成立了一個公司,居然繞過我們CPU就能把資料從網絡卡寫入硬碟中”,虎子火急火燎的來找我。

“不可能啊,按照我們之前的方案,怎麼說也得至少經過我們拷貝一次吧”

“根本不用,他們號稱是零拷貝技術”

我們趕緊放下手裡的工作,去打聽下究竟怎麼回事。

原來,Linux帝國最近新推出了一個API,叫sendfile

ssize_t sendfile(
  int out_fd, 
  int in_fd, 
  off_t *offset, 
  size_t count
  );

只需要指定開啟檔案的描述符和要傳送的網路介面描述符,就直接實現了把檔案通過網路發出去。

我們再次來到了作業系統I/O部門,對方一看是我們,熱情的接待了我們。

“你們來的正好,我還沒來得及告訴你們呢。上次你們提的思路非常好,帝國高層非常重視,我一反應上去,當即就採納了你們的意見。這不你們估計也知道了,推出了新的API給應用程式們使用,省去了資料白白去使用者空間轉一圈的開銷。一推出就大受歡迎,說起來還得感謝你們呢”

“原來是這樣,我說最近怎麼搬運資料的工作少了不少。不過你們是怎麼做到零拷貝的?”

 

 

I/O部門的人瞅了我們幾眼,得意的一笑,“帝國高層在討論你們的方案時,覺得還可以再進一步優化,直接把從硬碟讀取到的資料緩衝區地址和長度給到網路socket描述符,就不用你們再搬運一次資料,徹底解放你們,所以叫零拷貝啦!”

我倆連連點頭稱讚。

“還沒完呢!咱Linux帝國還把這一技術推廣到了檔案資料複製上,增加了另一個API:splice,以後檔案拷貝也可以減輕你們的負擔了”

ssize_t splice(
  int fd_in, 
  loff_t *off_in, 
  int fd_out,
  loff_t *off_out, 
  size_t len, 
  unsigned int flags
  );
 

我倆回去之後,把這一訊息告知了全廠,大家都高興壞了,原來各個車間都受苦久矣。

彩蛋1

在遙遠的Windows帝國上。

“部長,聽說Linux帝國推出了一個sendfile,號稱零拷貝”

“有這回事?咱們不能落後,趕緊去研究一下”

彩蛋2

Linux帝國新來了一家公司,專注網路資料包分析業務。

“老大,資料包每次都要經過Linux帝國協議棧部門處理一遍才能拿到,這太慢了”

“能不能繞開協議棧,直接抓包?”

預知後事如何,請關注後續精彩······

往期TOP5文章

太慢不能忍!CPU又拿硬碟和網絡卡開刀了!

因為一個跨域請求,我差點丟了飯碗

完了!CPU一味求快出事兒了!

雜湊表哪家強?幾大程式語言吵起來了!

一個HTTP資料包的奇幻