為何 Linux 在現代還堅持使用依賴這種動態庫的方式來做程序?

如果說在解放前,磁碟貴、內存貴、CPU性能低,那麼使用動態依賴來減少資源消耗,還情有可原。

但現在,什麼年代了,磁碟內存都按斤賣了,CPU的多路多核多線程更是家常便飯,Linux為何還要堅持以依賴的方法來做程序來噁心自己?難道就不能把所有依賴都靜態打包在一起方便普通用戶安裝,同時再提供一個源碼包給那些佔比非常小的特殊環境用戶使用?


最大的問題是, 升級一行代碼修復bug, 大家都下載500M(因為除了你軟體本身外還有一堆庫鏈接在一起了, 需要重新下載)的文件來升級?

一個庫需要升級一下, 所有靜態編譯的程序都需要升級. libstdc++升級一行代碼修復了一個溢出的問題, 於是你的系統提示你, 有4個G的更新需要被下載...


Windows 上那個 DLL 全名叫什麼來著?我記得好像是叫 動態鏈接庫


我給你一斤白菜,你給我 1T 內存啊?我很少見到內存 &>2G 的 VPS。甚至有些還是 256M 內存配置的,就因為負擔不起貴的。還有,你家路由器還有什麼什麼派有幾G內存啊?

內存永遠不夠用!記住,是永遠!內存多了怎麼辦,放數據啊,I/O 緩存、Redis 內存資料庫。有多少內存就可以吃掉你多少內存,然後運行起來飛快。

(知乎管理器快來扣我的友好度啊)

更新:把想吐槽的話都寫博客了,當然不完全是針對這個問題的: 為什麼我反對靜態鏈接?


640K內存對於任何人來說都足夠了

而且,你不用包管理系統的么


其實就主流的 Linux 發行版來說,這個問題大致有如下幾個:

第一,開發者不一定有權用靜態鏈接的方式發布所有的依賴庫

Linux 有很多開源的庫,但是開源跟開源之間是不同的,每個庫可以選擇不同的協議,以不同的協議發行,這其中,某些協議是允許自己的庫被靜態鏈接的,某些協議只允許這個庫被動態鏈接,或者換句話說,某些協議規定你只有動態鏈接這個庫,才能夠免除自身被開源。——如果你需要靜態鏈接,那麼你可能需要確保你使用的庫允許你發布靜態鏈接的版本。這並不總是可能的。

第二,一個程序不可能靜態鏈接所有的庫,依賴庫最終還是會依賴到系統提供的基礎庫(例如 glibc),每個不同的 Linux 版本中的同名依賴庫實際上是不同的編譯

對於 Windows 來說,由於只有 XP,7,等等這麼有限的幾個版本,那麼最終依賴的系統庫是可預期的。——但對於 Linux 來說,每個人的 Linux 本質上都是個不同的系統,可以理解為,Windows 一二十年來只發行了兩三個版本,而 Linux 發行了幾十上百個版本。。。每個系統的 glibc 都可能是不同的版本。那麼,你發行依賴庫時,究竟該選擇基於哪個版本的 glibc 來編譯呢?——是的,如果你要發行依賴庫,你就得考慮這些依賴庫在每個不同版本 Linux 的行為。而考慮到 Linux 版本的多樣化,這樣其實並不現實,讓依賴庫適配所有版本的 Linux 需要很大的工作量。而顯然,並沒有人付錢讓作者願意做這件一點也不 cooool 的事情。

嗯,我認為,對於普通的,基於 C 或者 C++ 的應用,Linux 要想全靜態發布,法律上可能不允許,技術上難度也很大。即便對於 Windows 而言,C#/Java 這種基於虛擬機的應用,虛擬機本身就是依賴,讓用戶自己安裝 .Net 或者 java 虛擬機作為依賴,現實中同樣面臨阻力,面臨著大家的不滿。

實際上,依賴問題是大多數程序的問題,也許你只是缺少一個靠譜的包管理器而已。


我要改個小bug,本來只要下個2m的文件就好,現在可好按照題主那麼一說我要下個5GB的文件!

題主 你也不要用win系統了,win也會噁心到你的!


我想問問樓主你的機器內存是多少的?磁碟性能又如何?

順著你這個思路下去,其實我可以這樣說,既然都這麼便宜了,咱們也不需要分頁,也不需要分段,也不需要交換了,這多好啊。一個程序靜態鏈接完了直接 MMAP 到內存里,跳到入口就開始跑,這多好?32bit 的上來就分 4G,64bit 的別分多了,就按 128GB 來吧,我想問問樓主你的機器能跑幾個程序?夠整數的么?

別的不說了,就拿 ffmpeg 做例子,基本上現在做視頻解碼的應用沒有不依賴它的。它一個靜態庫出來就幾十 MB 我沒記錯的話,你是準備三天兩頭的編譯一把把這個更新發給用戶對吧?


一定是沒用App Store升級過Xcode


寫程序的時候為什麼不把代碼全寫在main函數裡面,現在NTFS都支持4G以上的單文件了。


很棒的問題。

關於不把所有依賴都靜態打包在一起的原因,非不能也,實不為之。不這樣做的原因(或者說社區沒有普遍這樣做的原因), @Money No 說了其中很重要的一點,即這樣做需要付出的代價。樓上的大部分觀點也多是列舉這樣做的不足。大部分我都認可。可以上也僅僅是在說這樣做需要付出代價,毫不奇怪啊,免費的午餐本就不多。

不過我還是要來唱個反調,說說這樣做的好處,以及社區在這塊的的動態(利益相關,Ubuntu Server用戶 , CentOS 粉路過請輕黑)

靜態打包所有依賴的收益也是明顯的,首先共享庫的版本版本問題得到了很好的解決,不同的application可能依賴於不同版本的共享庫,而我們知道依賴衝突是一直是很蛋疼的一個問題。

那麼社區所採取的決定,便是在權衡受益和代價之後做出的,我個人倒是傾向於認為這是操作系統包管理系統發展的一個方向呢

如果都靜態打包了,那麼許多依賴便不復存在。你用過npm的話,你應該知道我在說什麼。

所以你看npm便是這個想法的一個實踐者,只是它不是操作系統級別的而已。

可即便是操作系統級別的依賴問題,也依然有社區在積極嘗試

Ubuntu Core便是其一,幾個月前Hacker News上幾次提到Ubuntu Core Snappy

這是個什麼東西呢

A Snappy application is basically a single compressed archive package with all the files contained within for the app to run. Yes, all the files, including the required library files. In other words, a single Snappy application contains all its dependencies within

你看,Snappy便是題主所說的「把所有依賴都靜態打包在一起」的具體實現,如此一來所有的包都是原子的,獨立且可回滾。

當然從維護角度提出的問題,共享庫升級的問題,確實也是很尖銳的一個反對意見,我完全認可這是個很大的代價。我覺得這是一個利益權衡的問題了。

此類問題,多是價值選擇的問題,以及是否符合使用的場景,按照慣常的做法,肯定會有一些人嘗鮮,也必定會有一方嗤之以鼻,最後能否被社區廣泛接受,倒不僅僅是技術的問題了。

另外本月又看到

Canonical has announced plans to switch all versions of Ubuntu to its new Snappy package manager

Snappy正在被整合進Ubuntu的所有版本里,包括Desktop和Server版,Ubuntu作為當今世界上最大的Linux發行版(沒有之一 : ) ), 已經在熱推這項技術了,不正說明這種方式正在被社區接受么或者至少在積極被嘗試


想學win那樣自帶依賴也不是不可以,但不需要編成靜態的。把動態庫全放在指定目錄然後編譯時用rpath參數指定位置就行了。


先給我來兩斤內存。。。


如果所有軟體都自帶一份自己所依賴的庫(可以是靜態庫,也可以是一份獨立的動態庫),那麼安裝是省事了,但不同軟體會用到同一個庫的不同版本,一方面浪費內存硬碟和網路流量,同時各個版本的庫中的bug(特別是安全漏洞)不便於統一修正(要修正的話就只能把補丁一個個merge到每個軟體各自的版本里去),皮膚之類的配置信息不一定能統一(新版接受的配置信息老版未必認識),用戶體驗可能也不盡一致。

所以發行版總會儘可能讓其中用到某一個庫的各個軟體都統一用該庫的某個較新版本,這樣用戶的使用效果會好一些,而這樣帶來的更複雜的依賴關係可由apt/yum之類工具自動處理,所需的整合和測試工作則由發行版或軟體的開發者替用戶完成。

當然,整合和測試也是有工作量的,發行版提供方可以處理熱門的軟體,軟體開發者可以處理熱門的發行版,剩下冷門/非開源軟體 x 冷門發行版(包括熱門發行版的冷門版本)的組合,如果不想要求用戶自行解決依賴關係的話,那也就只能放棄一些整合度,選一個最低限度的系統平台(例如只有內核、X、libc),把其中未提供的依賴庫一起打包到軟體里了。你抱怨某些第三方軟體難裝,其實也就是開發者太忙沒做這項工作而已(也可能是相關工具不夠完善導致這麼打包太麻煩),畢竟這跟直接丟一個源碼包出去指望用戶自行編譯或發行版幫忙整合相比,還是多了不少事情的。


首先windows也有動態庫,這是一種通用的做法。既然大家都使用,肯定是有道理的。除了內存外動態庫的優勢是管理方便,舉個例子:前一陣子ssl庫出現安全漏洞,如果使用動態庫只要升級動態庫就可以了,如果使用靜態庫編譯的話,成千上萬程序都要重編了。


唉,知乎果然微博化了


我想提主想表達的意思是,一個程序依賴如此多的第三方庫,安裝起來非常麻煩,庫的版本問題非常糾結,yum之類的命令覆蓋面有限且在無網路的環境下又不能用。相比windows一個安裝包解決所有問題,linux想從u盤拷貝一個程序直接安裝成功或者直接可運行簡直就是不可能的,所以我也在想,如果linux向易用性普世化發展,那麼,這個問題也是必須要解決的。

其實這個問題並不難解決,類似yum改成搜索本地文件即可,但還要多做一個隔離機制,不要再將所有庫都放到系統的目錄下,而像windows那樣每個程序的目錄是分離的,這麼做增加了部分冗餘卻大大增加了清晰度和可用性。可惜的是除了軟體從業人員,其他人幾乎不會用linux。我們這種習慣了linux糟糕的用戶體驗的碼農,不寫點讓人看不懂的命令反而覺得自己沒價值了。。。


因為復用,你能想像一個基礎的ABI庫在多少地方被用到么?如果都被copy一遍,你確定你的硬碟夠用么?


雖然依賴這玩意兒確實很噁心,但是不是Linux的錯,不然dll會很無辜,內存被你按斤賣,也很無辜


舉一個栗子。。。JNI(java native interface)就不支持靜態鏈接。。。我和師兄做的項目倒是想全部用靜態鏈接,奈何有些東西沒有靜態庫啊TAT


這種問題都問得出來,題主你應該好好回去學習下操作系統


推薦閱讀:

什麼是 Linux?
ubuntu linux 為什麼比Windows 安全得多?

TAG:Linux | Linux系統管理 | Linux軟體 | Linux開發 |