为什么如今的库还会被编译成 shared library 来用?内存和磁盘空间都已经足够了呀 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
fhc023
V2EX    Linux

为什么如今的库还会被编译成 shared library 来用?内存和磁盘空间都已经足够了呀

  •  
  •   fhc023 2019-01-13 18:32:51 +08:00 7462 次点击
    这是一个创建于 2464 天前的主题,其中的信息可能已经有所发展或是发生改变。

    主要是历史原因吗?是不是还有其他的理由?

    59 条回复    2019-03-09 16:01:43 +08:00
    ysc3839
        1
    ysc3839  
       2019-01-13 18:36:01 +08:00 via Android   1
    足够不代表可以随意浪费,当节约的成本几乎为 0 的时候为什么还要浪费?
    doun
        2
    doun  
       2019-01-13 18:37:24 +08:00 via iPhone
    版本管理等,编译时间等? golang 不就是全静态编译链接了吗
    Osk
        3
    Osk  
       2019-01-13 18:40:01 +08:00   2
    想起了被 node_modules 支配的恐惧,,,
    across
        4
    across  
       2019-01-13 18:41:50 +08:00
    为什么不用 shared lib,反而要采用浪费内存和磁盘的方法?
    thedrwu
        5
    thedrwu  
       2019-01-13 18:41:51 +08:00 via Android
    底层库的 hotfix/upgrade 不会牵一发而动全身

    Windows hook

    LGPL

    obj/linker 的兼容性

    等等
    fhc023
        6
    fhc023  
    OP
       2019-01-13 18:42:01 +08:00
    哦 我是觉得相对它的收益 成本有点高。作为库的使用者,得保证开发和生产环境的这些依赖版本都一致。还是很痛苦的。
    wbing
    &nsp;   7
    wbing  
       2019-01-13 18:43:11 +08:00
    改一个库的功能,把库替换了就好了,就不用把使用这个库的程序再重新编译一次
    fhc023
        9
    fhc023  
    OP
       2019-01-13 18:44:04 +08:00
    @doun 我很喜欢 go 呀 但是有很多有现有 c 库的情况就很尴尬。没太试过用 go 调用 c 不知道好不好
    shyangs
        10
    shyangs  
       2019-01-13 18:44:44 +08:00
    想起了被 node_modules 支配的恐惧
    ::doge::
    fhc023
        11
    fhc023  
    OP
       2019-01-13 18:45:27 +08:00
    @wbing 如果编译成 static library 的话也是不用重新编译的 只是打包一下
    fhc023
        12
    fhc023  
    OP
       2019-01-13 18:47:14 +08:00
    @Osk 哈哈 package-lock.json
    thedrwu
        13
    thedrwu  
       2019-01-13 18:54:06 +08:00 via Android
    @fhc023 如果操作系统的 runtime 打个补丁,需要重新安装所有的程序。还是说每个程序都静态链接一份操作系统?
    tewilove
        14
    tewilove  
       2019-01-13 19:00:28 +08:00 via Android
    库克:mmp。
    安卓:内存可能只够开个 QQ。
    WordTian
        15
    WordTian  
       2019-01-13 19:07:40 +08:00 via Android
    并不够,比如 office 软件要都搞成静态链接,开了这个你就不用干别的了
    catalina
        16
    catalina  
       2019-01-13 20:31:24 +08:00
    别开玩笑,你想折腾死那些官方源和镜像源吗(笑哭)
    fhc023
        17
    fhc023  
    OP
       2019-01-13 20:35:51 +08:00
    @thedrwu 有道理
    fhc023
        18
    fhc023  
    OP
       2019-01-13 20:38:11 +08:00
    我二了
    misaka19000
        19
    misaka19000  
       2019-01-13 20:45:20 +08:00   1
    我觉得对于客户端程序动态链接是有必要的,而对于服务端的程序则比较适合使用静态链接的程序
    danc
        20
    danc  
       2019-01-13 20:58:53 +08:00
    开玩笑吧。比如 windows 操作系统,你看有多少 dll 文件,你要静态链接了,编译一次得多久,而且你的内存能放得下不
    byteli
        21
    byteli  
       2019-01-13 21:14:21 +08:00 via Android
    很多是为了热更的
    expy     22
    expy  
       2019-01-13 21:30:58 +08:00
    作为用户还是喜欢普通应用层软件静态链接,下一个可执行文件到处都能跑。
    smdbh
        23
    smdbh  
       2019-01-13 21:31:00 +08:00
    1. 并不够
    2. 修改维护
    yanqiyu
        24
    yanqiyu  
       2019-01-13 21:39:09 +08:00   1
    glibc:我现在要修一个 BUG,请问你准备更新几个软件呢
    fhc023
        25
    fhc023  
    OP
       2019-01-13 22:58:24 +08:00
    仔细想了下。像底层库更新这种情况的话,用动态库确实可以不用让依赖它的库重新打包。如果接口和行为没有改变的话是很不错的,但是也是可能带来兼容性问题。比如,底层库做了个 breaking change,那后续的库如果不改动的话也不能跑了。目前这种情况主要是包管理器来做依赖检查,然后决定你不是能更新某个底层库的。所以我觉得各有利弊吧。
    kljsandjb
        26
    kljsandjb  
       2019-01-13 23:04:05 +08:00 via iPhone
    不说磁盘,内存这玩意不管多大都是稀缺资源
    dalieba
        27
    dalieba  
       2019-01-13 23:10:13 +08:00 via Android
    降低开发成本,尤其是几个程序或者操作都需要一个轮子的时候。
    dangyuluo
        28
    dangyuluo  
       2019-01-14 01:24:37 +08:00
    建议读一读《程序员的自我修养-链接、装载和库》,有真相
    sdijeenx
        29
    sdijeenx  
       2019-01-14 02:58:10 +08:00
    磁盘空间本来是够的,自从有了 SSD 之后又不够了;
    内存空间本来是够的,自从有了 DDR4 之后又不够了。
    Ediacaran
        30
    Ediacaran  
       2019-01-14 06:54:46 +08:00 via Android
    插件,或者方便替换
    hikkikuma1991
        31
    hikkikuma1991  
       2019-01-14 09:08:31 +08:00
    有些库没办法被静态连接,以 glibc 那一坨为代表。golang 默认也是动态链接 glibc 的。
    fhc023
        33
    fhc023  
    OP
       2019-01-14 09:51:09 +08:00
    @hikkikuma1991 长知识了 具体为啥必须要动态链接 大概是因为这个 https://skarnet.org/software/nsss/nsswitch.html
    enenaaa
        34
    enenaaa  
       2019-01-14 09:53:13 +08:00
    静态链接一个符号重名就能折腾死你。
    fhc023
        35
    fhc023  
    OP
       2019-01-14 09:53:15 +08:00
    话说这个问题原来在 YC 上就有讨论 感觉水很深呐
    http://harmful.cat-v.org/software/dynamic-linking/
    https://news.ycombinator.com/item?id=9629663
    msg7086
        36
    msg7086  
       2019-01-14 09:56:25 +08:00
    @fhc023 #25 所以发行版更新底层库都会保证 API 不会出现 breaking change。
    比如 openssl 1.0.2 和 1.0.2abcdef....opqr 都是兼容的。
    而且像是 libssl libc 这种库,正是动态链接的优势所在。系统库一更新,所有依赖的软件自动受益,即使你用的软件已经好几年不更新了,只要依赖的底层库更新,一样能修正掉对应的安全漏洞。
    reself
        37
    reself  
       2019-01-14 10:59:58 +08:00
    代码上都要做解耦,讲究代码复用呢,为啥要反其道而行?
    bytelee
        38
    bytelee  
       2019-01-14 11:32:15 +08:00
    难道动态库只是为了解决磁盘和内存空间不足的问题么?
    iwtbauh
        39
    iwtbauh  
       2019-01-14 12:52:56 +08:00 via Android
    @fhc023 #25

    这就是我为什么讨厌 windows 这种大泥球的原因之一啊。你要是 windows 用户,肯定知道臭名昭著的“ DLL 地狱”问题。DLL 地狱即一个新软件可以随意升级(或降级)现有软件依赖的 DLL 库,而应用程序通常需要特定版本的库,一旦没有特定版本的库,应用程序就会崩溃。

    这就是因为 windows 技术上一开始没有做好共享库版本控制问题导致的。也就是你说的这个原因。现在为了保证前向兼容采用了一种极其丑陋的方法规避问题,但没能实际解决。

    而 Unix 的世界里,共享库版本控制做的非常好,一种方法是库文件名后戳通常带有版本号,应用程序依赖 libxxx.so.1 然后系统将 libxxx.so.1 符号链接到 libxxx.so.1.2.3 等版本上,系统只管升级 libxxx.so.1.x.x,库开发者保证小版本变化不会引入回归。而引入回归的大版本通常也可以和旧版本库共存。除了这种方法,还有很多种方法,比如 glibc 的符号版本控制,还有 qt 的库版本控制。。
    littlewing
        40
    littlewing  
       2019-01-14 13:19:12 +08:00
    你是不是对 shared library 有什么误解? shared library 从来都是不使用从来解决内存和磁盘不够的问题的。
    hilbertz
        41
    hilbertz  
       2019-01-14 13:25:09 +08:00
    确实没有太大意义,共享库主要是为了商业分发
    lcdtyph
        42
    lcdtyph  
       2019-01-14 13:37:10 +08:00 via iPhone
    @littlewing 还是解决了一些内存问题的吧?
    XIVN1987
        43
    XIVN1987  
       2019-01-14 14:23:04 +08:00
    python 可以很方便的调用 C/C++编写的 dll 库,,如果是静态连接库的话,,必须得装 C/C++编译器才能使用,,
    RqPS6rhmP3Nyn3Tm
        44
    RqPS6rhmP3Nyn3Tm  
       2019-01-14 14:45:24 +08:00 via iPhone
    想起了被 glibc 支配的恐惧
    w01230
        45
    w01230  
       2019-01-14 15:12:14 +08:00
    够用了也别浪费呀, 也有成本问题, ……看看 OPENWRT 的路由器~
    ysc3839
        46
    ysc3839  
       2019-01-14 16:00:03 +08:00 via Android
    @iwtbauh
    Windows 没有共享库版本控制,那么应用需要用的库不都是自己打包吗?再怎么升级也不会影响到别的软件呀?
    你可能会说 VC++ 运行库是共享的,但是 VC++ 本身不同版本是分开的,文件名中就包含有主版本号,同一个主版本要保证兼容的。

    你说 Unix 共享库版本控制做的非常好,本质不是 Unix 做得好,而是大多数类 Unix 系统有包管理,通过包管理能很好地做到版本控制。像 macOS 这种没有自带包管理的系统,也是像 Windows 这样软件需要什么就自己打包的。
    janxin
        47
    janxin  
       2019-01-14 16:03:17 +08:00
    编译快算不算优点?
    est
        48
    est  
       2019-01-14 16:11:33 +08:00   1
    @iwtbauh dll 地狱早就被 winsxs 解决了。win98 时代说这个还有道理,现在说就是老黄历了。

    linux 下不同 distro、甚至同一 distro 不同版本 之间根本谈不上 .so 兼容。那种加版本的 trick 就不要拿出来 show 了。
    fhc023
        49
    fhc023  
    OP
       2019-01-14 16:36:05 +08:00
    @iwtbauh 我觉得是有道理的 但是 linux 上的版本问题就算被解决了 但是还是感觉很奇怪 因为如果上层都各自用各自的版本了,那干嘛还要 shared library。 反而为了解决这些版本问题增加了复杂度 感觉不值得。不过像 @w01230 说的这种内存特别紧缺的是很有用的。而且还有像 glibc 这种不知道是有历史包袱还是故意为之的情况存在。所以我觉得看情况,像我能用 static 的时候就尽量用 static。虽然最终出来的 executable 里还是有 so 只要解决了生产环境的兼容问题 我就能接受了。
    fhc023
        50
    fhc023  
    OP
       2019-01-14 16:38:15 +08:00
    感觉学到了很多哈 谢谢大家 如果大家有各种奇妙的关于这问题的链接都可以 po 出来
    est
        51
    est  
       2019-01-14 16:38:45 +08:00
    @fhc023 尽量 static 有一个特别的坑。就是遇到大规模安全事故需要普遍升级的时候

    那个时候你就哭吧。2333
    behanga
        52
    behanga  
       2019-01-14 16:53:35 +08:00
    当你吐槽 XXX 这破 app 都 100/200 多 MB 的时候 有可能里面的 so 就没用 shared library
    IdontWanToBeBan
        53
    IdontWanToBeBan  
       2019-01-14 16:59:34 +08:00
    随意用这不好吗。。
    iwtbauh
        54
    iwtbauh  
       2019-01-14 18:14:59 +08:00 via Android
    @ysc3839 #46

    你怕是不知道以前很多应用程序安装时直接升级(降级)系统库。

    而且这种行为的应用程序到现在也是存在的。

    @est #48

    这个问题和 distro 之间不兼容没有半点关系。

    所以说我说是“现在为了保证前向兼容采用了一种极其丑陋的方法规避问题”啊。

    @fhc023 #49

    比如我为 Debian 的某个版本提供二进制包,我可以直接在系统里依赖库,比如 libcurl3。而且基于共享库版本控制,不用担心 API/ABI 变化。安全更新直接由发行版负责了。我也不用自己去编译一份 curl,为什么不用呢。
    fhc023
        55
    fhc023  
    OP
       2019-01-14 18:19:02 +08:00
    @est 嗯 谢谢提醒 自己写的哪些项目分别有哪些依赖都在自动化脚本里 如果有哪个出了问题 grep 下就知道哪些需要重新 link 之后重新编译有 bug 的库 然后 link 一下就完了 不需要全部重新编译 我觉得问题应该不大。
    fhc023
        56
    fhc023  
    OP
       2019-01-14 18:26:19 +08:00
    @iwtbauh # 54
    你说的很有道理啊,可惜我的开发环境和部署环境不是同一个 distro。比如我在 arch 上依赖 ffmpeg 某个 shared lib 写了程序 在部署环境的 debian 里跑不起来 debian 官方可能都不提供我依赖的这个 lib 版本。
    fhc023
        57
    fhc023  
    OP
       2019-01-14 18:54:42 +08:00
    @behanga 感觉更可能是图片啥的,毕竟一个 linux kernel image 也才几十 MB
    ysc3839
        58
    ysc3839  
       2019-01-14 19:01:31 +08:00 via Android
    @iwtbauh 那也不能怪操作系统啊,应用程序随意修改系统文件,在任何系统上都有可能出问题吧?
    kwest
        59
    kwest  
       2019-03-09 16:01:43 +08:00
    1. 方便分发和更新,动态库更新一处即可,而不必像静态库一样把所有依赖于该库的二进制文件全部更新。
    2. 节省内存和硬盘,动态库代码段被所有依赖它的程序共享并在内存中只存在一份。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     916 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 18:51 PVG 02:51 LAX 11:51 JFK 14:51
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86