Unix的內存分配方式是否有缺點,能否改進?

在王垠的博客(我和權威的故事)上看到這段話

Unix 的內存管理是按「頁」而不是按「結構」分配,相當於把內存分配的任務完全推給應用程序。而且允許任意的指針操作,這就像給每個老百姓一把愛走火的槍。可是又想要「安全」,自相矛盾。沒辦法,不得不強制進程數據空間完全隔離,使得進程間無法直接傳遞數據結構。進程和線程上下文切換開銷過大,造成了使用大規模並發或者分散式計算的瓶頸,導致了 goroutine 和 node.js 等「變通方法」的產生。

這段話說得是否正確?為什麼內存管理按「頁」分配就相當於把內存分配的任務交給應用程序,難道頁面更換的操作不是由操作系統負責與實現的嗎?(比如,C程序員雖然需要malloc和free分配內存,但底層的頁面更換演算法是由操作系統自動調度的吧)


謝邀

我猜測王垠之所以這麼說,是因為他認為計算機軟硬體系統應該整體設計成一個單一高級語言的運行環境,和實現機制相關的概念(如內存頁)是不應該暴露出來的。這種設計的好處是

  1. 避免很多不必要的問題:跨隔離邊界的數據序列化,反序列化/解析
  2. 可以減少用戶犯錯的機會:用戶不用管理裸內存,裸IO設備等低級概念
  3. 節省很多不必要的概念:OS、資料庫、文件系統什麼的都還原成語言使用的庫和一個自動管理/持久化的環境。甚至進程這個概念都可以不要
  4. 解決問題的方式更簡單:單一語言源代碼就可以搞定所有問題,更容易理解和被重用
  5. 計算機回歸「計算」這個本質:大家只要把自己要做的事表達成計算問題,然後用源代碼給出方案即可

以上的觀點我都是同意的,而且Lisp Machine等先鋒/先驅也實踐過了這個想法

可是,為什麼現實世界的主流不採用這種方式來設計計算機軟硬體系統呢?我想原因可能在於2點

  1. 現在的(分層式的)軟硬體體系並不排斥單一語言系統這個概念。實際上,只要在用戶態設計一個語言運行環境,然後把底層系統、細節隱藏就行了。而且同時保留底層系統又有很多好處:可以以最手動優化的方式追求極致的性能,可以換用其它的「單一語言系統」,可以多語言系統協作
  2. 終極的、值得所有人同意的「單一語言」從來沒有被成功設計出來,以後也不一定會。比如:現在被津津樂道的函數式編程範式(Functional Programming),由於其純粹形式不允許變數,導致在演算法複雜度上永遠落後於命令式編程範式(Imperative Programming);而非純粹形式又等於組合了雙方面的缺點,還不如用兩種範式的語言通過OS協作。很多人在實踐以後,也放棄了在這棵樹上弔死的想法


Unix 沒規定 kernel 之上就是 app。


進程間沒有隔離?嗯,這一定是破壞分子心目中完美的世界……


把內存分配的任務交給應用程序這應該是特性而不是缺陷。因為應用程序只有自己控制內存分配才能選擇對具體問題最優的解決方案,至於不需要自己定製內存分配策略的應用程序完全可以用庫來解決這個任務。libc中內置的malloc/free就是例子。如果一項功能在應用層實現既沒有損失效率也沒有提高開發的複雜性還能提供更好的靈活性,為什麼不放到應用層?

把指針操作暴露給用戶還是特性而不是缺陷。因為這給應用程序提供了足夠的表達能力。安全性什麼的根本不是問題,因為沒有誰阻止你把這些底層操作封裝成高級語言。如果用戶不喜歡底層的複雜環境,那麼使用高級語言就解決了這個問題。暴露低層介面並沒有阻止用戶使用高層介面。

進程或者線程的上下文切換開銷大的原因是軟體的抽象層次多造成的,跟內存管理什麼的沒什麼關係。抽象層次越多,上下文(context)越複雜,上下文切換(context switch)的開銷就越大。

王同學在程序語言設計上一直很追求簡潔正交有表達能力的特性而反對各種功能特性的堆砌,不知道為什麼在操作系統設計卻反其道而行之?Unix系統這種提供基於頁面的內存管理或基於流的文件系統難道不是和Lisp提供基於S-expression的語法有相同的出發點?介面需要簡潔有表達能力而不是功能的堆砌,難道這不是王同學一直吐槽各種語言的話嗎?


goroutine 和 node.js?這兩個東西有什麼可比性?

不爽 Unix 進程的人去做了 Erlang 出來,假設操作系統是個白痴然後自己把所有東西乾淨利落做掉;王垠做了什麼?

------

回頭說。UNIX 相信的是給程序員提供最大的靈活性,同時保證系統的公平和健康;所以 UNIX 利用進程作為資源保護的強制邊界,邊界絕對不允許越過,但邊界之內,給程序員最大的自由。按頁分配內存允許程序自己實現任意邏輯的 caching、pooling,而不依賴系統強制的策略。同時,這些策略通常都有底層的「庫」(如 libc,如 tcmalloc)負責,而普通的程序員一樣不需要擔心這裡隱藏的複雜度。這種「讓合適的人做合適的事」、協同完成複雜任務的方法,才是 UNIX 的精髓。

每個人幻想中都有一個完美世界,只不過王垠的幻想世界沒法執行而已。


所以「高手」們都在做著把應用程序整合進內核以求高性能不通用的事兒。


推薦閱讀:

PV、TPS、QPS是怎麼計算出來的?
如何看待加密即時通信APP——安司密信?
國內知名的 Linux 程序員有哪些?
學習linux驅動開發的方法?
Linux下mysql讀寫速度為什麼很慢?

TAG:Linux | 計算機 | Unix | 內存RAM |