V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
fhc023
V2EX  ›  Linux

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

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

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

    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
        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   ·   实用小工具   ·   5724 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 01:39 · PVG 09:39 · LAX 17:39 · JFK 20:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.