AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

Linux下被我誤解的gcc,軟件可執(zhí)行文件的跨系統(tǒng)版本兼容性沒有那么差,如果你也是這樣處理

來源: 責(zé)編: 時間:2023-12-22 17:13:49 317觀看
導(dǎo)讀[開發(fā)]為什么不建議交付靜態(tài)鏈接的可執(zhí)行文件給用戶?為什么Golang開發(fā)的軟件單文件直接丟到各種Linux系統(tǒng)就能運(yùn)行?[開發(fā)+運(yùn)維] Linux從外到內(nèi)剝開動態(tài)庫,1個簡單例子看懂Linux下的動態(tài)庫開發(fā)原理以上是近期發(fā)布的這3
  • [開發(fā)]為什么不建議交付靜態(tài)鏈接的可執(zhí)行文件給用戶?
  • 為什么Golang開發(fā)的軟件單文件直接丟到各種Linux系統(tǒng)就能運(yùn)行?
  • [開發(fā)+運(yùn)維] Linux從外到內(nèi)剝開動態(tài)庫,1個簡單例子看懂Linux下的動態(tài)庫開發(fā)原理

以上是近期發(fā)布的這3篇文章,圍繞Linux下的可執(zhí)行文件究竟是采用靜態(tài)鏈接還是動態(tài)鏈接方式發(fā)布,從不同角度做了分析。看起來第1、2篇的觀點(diǎn)是相反的。現(xiàn)在對這兩個看似矛盾的說法加以解釋,以期讀者能對Linux的動態(tài)庫、靜態(tài)編譯可執(zhí)行文件的理解,和我一樣在學(xué)習(xí)進(jìn)步,形成總體符合實(shí)際的認(rèn)知。BXl28資訊網(wǎng)——每日最新資訊28at.com

也得到了讀者的很多反饋,現(xiàn)舉例其一:BXl28資訊網(wǎng)——每日最新資訊28at.com

BXl28資訊網(wǎng)——每日最新資訊28at.com

為什么要盯住gcc呢?因?yàn)長inux的軟件生態(tài)中,C/C++開發(fā)的軟件,特別是基礎(chǔ)型軟件、需要高性能的軟件,往往歷史原因都以這兩種語言為主,在此不贅述。BXl28資訊網(wǎng)——每日最新資訊28at.com

總之,因?yàn)镃/C++開發(fā)的軟件占比很大,即使開發(fā)業(yè)務(wù)中不直接使用,也會在運(yùn)行中依賴到C/C++的庫或可執(zhí)行文件的功能。搞懂動態(tài)庫的特性,對于解決一些軟件依賴問題、開發(fā)編譯鏈接失敗問題,都有幫助。所以開發(fā)者和運(yùn)維仍然有必要增進(jìn)這方面的理解。BXl28資訊網(wǎng)——每日最新資訊28at.com

1.動態(tài)鏈接適合插件化開發(fā)、插件化升級、希望打包發(fā)布的可執(zhí)行文件盡量小的場景;而靜態(tài)鏈接方式適合易部署、不想處理第三方動態(tài)庫依賴問題的場景。BXl28資訊網(wǎng)——每日最新資訊28at.com

2.gcc/g++ 作為Linux下主要的編譯器,支持動態(tài)鏈接、靜態(tài)鏈接方式。如最基本的main.c 代碼可通過gcc -o main_dynamic_link main.c 和 gcc -static -o main_static main.c 分別得到兩類可執(zhí)行文件。這是大學(xué)生在學(xué)校初學(xué)Linux下的gcc C/C++編程的時候就了解的。BXl28資訊網(wǎng)——每日最新資訊28at.com

3.gcc 動態(tài)鏈接生成的可執(zhí)行文件,因?yàn)榇a必然使用到c/c++的標(biāo)準(zhǔn)庫提供的函數(shù),那么可執(zhí)行文件必然要與libc.so庫動態(tài)庫鏈接(如下圖)。BXl28資訊網(wǎng)——每日最新資訊28at.com

BXl28資訊網(wǎng)——每日最新資訊28at.com

4.gcc編譯得到的可執(zhí)行文件,運(yùn)行時會以進(jìn)程方式在用戶態(tài)、內(nèi)核態(tài)的內(nèi)存中布局。如果可執(zhí)行文件是動態(tài)鏈接方式的,則運(yùn)行時由 Linux內(nèi)核負(fù)責(zé)載入ELF格式的可執(zhí)行文件后,內(nèi)核通過 ld-linux.so (64位系統(tǒng)下則為 ld-linux-x86-64.so ) 分析可執(zhí)行文件依賴的其他動態(tài)庫信息,由ld-linux.so 負(fù)責(zé)逐個載入其他動態(tài)庫到該進(jìn)程的虛擬內(nèi)存的代碼段位置中。這里就發(fā)揮了動態(tài)庫和虛擬內(nèi)存的優(yōu)勢:熱門的動態(tài)庫被很多其他進(jìn)程依賴,那么這種可執(zhí)行文件實(shí)際只占用物理內(nèi)存的一塊空間,無論被多少個進(jìn)程依賴。BXl28資訊網(wǎng)——每日最新資訊28at.com

所以達(dá)到了提高內(nèi)存利用率的效果,這對于需要運(yùn)行大量軟件的場景(如Linux桌面),收益還是可觀的。可執(zhí)行文件從被調(diào)起到執(zhí)行完畢,我們可以用 strace 命令看到全過程,包括需要讀取的其他庫文件的過程。比如下面的可執(zhí)行文件可以用strace 看到執(zhí)行全流程(功能只調(diào)用printf函數(shù)打印字符串)。BXl28資訊網(wǎng)——每日最新資訊28at.com

root@localhost:~# file  ./main./main: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=82e7afc31da1cdbdd374658c2724dce983ccedab, for GNU/Linux 3.2.0, not strippedroot@localhost:~# ldd  ./main        not a dynamic executable   #說明當(dāng)前是靜態(tài)鏈接的                root@localhost:~# strace ./mainexecve("./main", ["./main"], 0x7ffe6fd2a090 /* 25 vars */) = 0arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe7ada0370) = -1 EINVAL (Invalid argument)brk(NULL)                               = 0x1a12000brk(0x1a12dc0)                          = 0x1a12dc0arch_prctl(ARCH_SET_FS, 0x1a123c0)      = 0set_tid_address(0x1a12690)              = 27080set_robust_list(0x1a126a0, 24)          = 0rseq(0x1a12d60, 0x20, 0, 0x53053053)    = 0uname({sysname="Linux", nodename="localhost", ...}) = 0prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0readlink("/proc/self/exe", "/root/main", 4096) = 10getrandom("/xa1/xe6/x48/xa4/x1d/x32/xef/x0e", 8, GRND_NONBLOCK) = 8brk(0x1a33dc0)                          = 0x1a33dc0brk(0x1a34000)                          = 0x1a34000mprotect(0x4c1000, 16384, PROT_READ)    = 0newfstatat(1, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0write(1, "111", 3111)                      = 3exit_group(3)                           = ?+++ exited with 3 +++## 下面按動態(tài)鏈接生成可執(zhí)行文件root@localhost:~# gcc  -o main main.c## strace 顯示可執(zhí)行文件 執(zhí)行時需要加載 `/lib/x86_64-linux-gnu/libc.so.6` 文件。root@localhost:~# strace ./mainexecve("./main", ["./main"], 0x7ffec2fb69c0 /* 25 vars */) = 0brk(NULL)                               = 0x55fd3f1bc000root@localhost:~#mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa3491dd000access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=87359, ...}, AT_EMPTY_PATH) = 0mmap(NULL, 87359, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa3491c7000close(3)                                = 0openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3read(3, "/177ELF/2/1/1/3/0/0/0/0/0/0/0/0/3/0>/0/1/0/0/0P/237/2/0/0/0/0/0"..., 832) = 832pread64(3, "/6/0/0/0/4/0/0/0@/0/0/0/0/0/0/0@/0/0/0/0/0/0/0@/0/0/0/0/0/0/0"..., 784, 64) = 784pread64(3, "/4/0/0/0 /0/0/0/5/0/0/0GNU/0/2/0/0/300/4/0/0/0/3/0/0/0/0/0/0/0"..., 48, 848) = 48pread64(3, "/4/0/0/0/24/0/0/0/3/0/0/0GNU/0 =/340/2563/265?/356/25x/261/27/313A#/350"..., 68, 896) = 68newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2216304, ...}, AT_EMPTY_PATH) = 0pread64(3, "/6/0/0/0/4/0/0/0@/0/0/0/0/0/0/0@/0/0/0/0/0/0/0@/0/0/0/0/0/0/0"..., 784, 64) = 784mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fa348f9f000mmap(0x7fa348fc7000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7fa348fc7000mmap(0x7fa34915c000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fa34915c000mmap(0x7fa3491b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7fa3491b4000mmap(0x7fa3491ba000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa3491ba000close(3)                                = 0mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa348f9c000arch_prctl(ARCH_SET_FS, 0x7fa348f9c740) = 0set_tid_address(0x7fa348f9ca10)         = 27089set_robust_list(0x7fa348f9ca20, 24)     = 0rseq(0x7fa348f9d0e0, 0x20, 0, 0x53053053) = 0mprotect(0x7fa3491b4000, 16384, PROT_READ) = 0mprotect(0x55fd3e9e1000, 4096, PROT_READ) = 0mprotect(0x7fa34921d000, 8192, PROT_READ) = 0prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0munmap(0x7fa3491c7000, 87359)           = 0newfstatat(1, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0getrandom("/x84/x8c/x06/x16/x25/xe5/x97/x97", 8, GRND_NONBLOCK) = 8brk(NULL)                               = 0x55fd3f1bc000brk(0x55fd3f1dd000)                     = 0x55fd3f1dd000write(1, "111", 3111)                      = 3exit_group(3)                           = ?+++ exited with 3 +++root@localhost:~#

可以看到 動態(tài)鏈接的C可執(zhí)行文件運(yùn)行時確實(shí)需要加載 /lib/x86_64-linux-gnu/libc.so.6 文件。而靜態(tài)鏈接的可執(zhí)行文件沒有加載任何.so文件,包括libc.so也不需要。因?yàn)殪o態(tài)文件的代碼指令已完整在文件中。BXl28資訊網(wǎng)——每日最新資訊28at.com

root@localhost:~# gcc --versiongcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0Copyright (C) 2021 Free Software Foundation, Inc.This is free software; see the source for copying conditions.  There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.root@localhost:~# gcc -static -o main_static main.c  # 靜態(tài)鏈接root@localhost:~# gcc  -o main_shared_link main.c    # 動態(tài)鏈接root@localhost:~# ls -lhttotal 1.8M-rwxr-xr-x 1 root root  16K Dec 17 23:58 main_shared_link-rwxr-xr-x 1 root root 880K Dec 17 23:58 main_static-rw-r--r-- 1 root root   54 Dec 17 22:30 main.croot@localhost:~# file main_static   # 查看靜態(tài)鏈接文件的屬性main_static:      ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=82e7afc31da1cdbdd374658c2724dce983ccedab, for GNU/Linux 3.2.0, not strippedroot@localhost:~# main_shared_link  # 查看動態(tài)鏈接文件的屬性main_shared_link: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f14401e673b52624535874f2e1a8488a0edbc891, for GNU/Linux 3.2.0, not strippedroot@localhost:~# ls -lht /lib/x86_64-linux-gnu/libc.so.6-rwxr-xr-x 1 root root 2.2M Nov 22 21:18 /lib/x86_64-linux-gnu/libc.so.6

這里看到:880K Dec 17 23:58 main_static靜態(tài)文件大小880K,而libc.so大小2.2M 。靜態(tài)文件大小比C標(biāo)準(zhǔn)庫動態(tài)文件的大小還小很多。BXl28資訊網(wǎng)——每日最新資訊28at.com

說明gcc并不只是把libc.so的所有函數(shù)完全包含進(jìn)靜態(tài)可執(zhí)行文件,而這是我之前對gcc的誤解。BXl28資訊網(wǎng)——每日最新資訊28at.com

實(shí)際gcc對靜態(tài)的鏈接是做了精簡優(yōu)化的,只保留了有被調(diào)用的函數(shù)代碼到最終可執(zhí)行文件內(nèi)。BXl28資訊網(wǎng)——每日最新資訊28at.com

5.所以本文最初提到的《為什么不建議交付靜態(tài)鏈接的可執(zhí)行文件給用戶?》 中的不建議,是只從靜態(tài)文件的分發(fā)方式降低了系統(tǒng)基礎(chǔ)庫的重用率的角度出發(fā)的。當(dāng)然隨著技術(shù)的進(jìn)步,也許以后內(nèi)核的可執(zhí)行文件加載器能做到識別出靜態(tài)文件中的某些可替代的公共部分就自動剔除對物理內(nèi)存的占用,而借助系統(tǒng)已有的已載入內(nèi)存的公共代碼實(shí)現(xiàn)替代,而不影響軟件功能,就結(jié)合了動態(tài)和靜態(tài)的兩種優(yōu)勢。這只是一個猜想,并非合理完美的方案。BXl28資訊網(wǎng)——每日最新資訊28at.com

6.而《為什么Golang開發(fā)的軟件單文件直接丟到各種Linux系統(tǒng)就能運(yùn)行?》中g(shù)olang能做到的,gcc也能做到,所以C/C++靜態(tài)鏈接的可執(zhí)行文件的跨系統(tǒng)版本兼容性沒有那么差,跟Golang生成的靜態(tài)可執(zhí)行文件是一樣能丟到各種Linux發(fā)行版的運(yùn)行的。BXl28資訊網(wǎng)——每日最新資訊28at.com

7.但跨系統(tǒng)兼容性的前提是32位、64位系統(tǒng)和軟件的數(shù)位,要匹配。除非32位的系統(tǒng)內(nèi)核支持PAE特性或Linux系統(tǒng)額外安裝了 multilib 庫,以實(shí)現(xiàn)32位系統(tǒng)下運(yùn)行64位的軟件,或64位系統(tǒng)下運(yùn)行32位的軟件。BXl28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-52183-0.htmlLinux下被我誤解的gcc,軟件可執(zhí)行文件的跨系統(tǒng)版本兼容性沒有那么差,如果你也是這樣處理

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: JS問題:如何實(shí)現(xiàn)文本一鍵復(fù)制和長按復(fù)制功能?

下一篇: 在三分鐘內(nèi)學(xué)習(xí)二分查找

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 把LangChain跑起來的三個方法

    使用LangChain開發(fā)LLM應(yīng)用時,需要機(jī)器進(jìn)行GLM部署,好多同學(xué)第一步就被勸退了,那么如何繞過這個步驟先學(xué)習(xí)LLM模型的應(yīng)用,對Langchain進(jìn)行快速上手?本片講解3個把LangChain跑起來
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 一年經(jīng)驗(yàn)在二線城市面試后端的經(jīng)驗(yàn)分享

    忠告這篇文章只適合2年內(nèi)工作經(jīng)驗(yàn)、甚至沒有工作經(jīng)驗(yàn)的朋友閱讀。如果你是2年以上工作經(jīng)驗(yàn),請果斷劃走,對你沒啥幫助~主人公這篇文章內(nèi)容來自 「升職加薪」星球星友 的投稿,坐
  • 分布式系統(tǒng)中的CAP理論,面試必問,你理解了嘛?

    對于剛剛接觸分布式系統(tǒng)的小伙伴們來說,一提起分布式系統(tǒng),就感覺高大上,深不可測。而且看了很多書和視頻還是一臉懵逼。這篇文章主要使用大白話的方式,帶你理解一下分布式系統(tǒng)
  • 讓我們一起聊聊文件的操作

    文件【1】文件是什么?文件是保存數(shù)據(jù)的地方,是數(shù)據(jù)源的一種,比如大家經(jīng)常使用的word文檔、txt文件、excel文件、jpg文件...都是文件。文件最主要的作用就是保存數(shù)據(jù),它既可以保
  • 微軟邀請 Microsoft 365 商業(yè)用戶,測試視頻編輯器 Clipchamp

    8 月 1 日消息,微軟近日宣布即將面向 Microsoft 365 商業(yè)用戶,開放 Clipchamp 應(yīng)用,邀請用戶通過該應(yīng)用來編輯視頻。微軟于 2021 年收購 Clipchamp,隨后開始逐步整合到 Microsof
  • 慕巖炮轟抖音,百合網(wǎng)今何在?

    來源:價值研究所 作者:Hernanderz“難道就因?yàn)樽约旱囊粋€產(chǎn)品牛逼了,從客服到總裁,都不愿意正視自己產(chǎn)品和運(yùn)營上的問題,選擇逃避了嗎?”這一番話,出自百合網(wǎng)聯(lián)合創(chuàng)
  • 當(dāng)家的盒馬,加速謀生

    來源 | 價值星球Planet作者 | 歸去來自己“當(dāng)家”的盒馬,開始加速謀生了。據(jù)盒馬官微消息,盒馬計劃今年開放生鮮供應(yīng)鏈,將其生鮮商品送往食堂。目前,盒馬在上海已經(jīng)與
  • 3699元!iQOO Neo8 Pro頂配版今日首銷:1TB UFS 4.0同價位唯一

    5月23日,iQOO推出了全新的iQOO Neo8系列,包含iQOO Neo8和iQOO Neo8 Pro兩個版本,其中標(biāo)準(zhǔn)版搭載高通驍龍8+,而Pro版更是首發(fā)搭載了聯(lián)發(fā)科天璣9200+旗艦
Top