亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Table of Contents
Why dynamic linking? " >Why dynamic linking?
How to perform dynamic linking? " >How to perform dynamic linking?
動態(tài)鏈接的方式" >動態(tài)鏈接的方式
延遲綁定技術" >延遲綁定技術
顯式運行時鏈接" >顯式運行時鏈接
總結" >總結
Home System Tutorial LINUX What is the original meaning of dynamic linking and static linking in Linux?

What is the original meaning of dynamic linking and static linking in Linux?

Feb 05, 2024 pm 05:45 PM
linux linux tutorial linux system Lazy loading linux command shell script embeddedlinux good promise Getting started with linux linux learning

Old rules, first ask a few questions:

  • Why dynamic linking?
  • How to do dynamic linking?
  • What is address-independent code technology?
  • What is delayed binding technology?
  • How to do explicit linking while the program is running?

Why dynamic linking?

The emergence of dynamic linking is to solve some shortcomings of static linking:

  1. Save memory and disk space: As shown in the figure below,
Linux 動態(tài)鏈接與靜態(tài)鏈接原來是這么回事?

Program1 and Program2 contain two modules, Program1.o and Program2.o respectively, and they both require the Lib.o module. In the case of static linking, both target files use the Lib.o module, so they have copies in the executable files Program1 and program2 output by the link at the same time. When running at the same time, Lib.o has two copies on the disk and in the memory. Copies, when there are a large number of multiple programs similar to Lib.o sharing target files in the system, a lot of space will be wasted.

  1. Static linking is very unfriendly to program update deployment and release

If a module depends on 20 modules, when one of the 20 modules needs to be updated, all modules need to be found and recompiled into an executable program before the update can be successful. Each time any module is updated, For a module, the user needs to re-obtain a very large program. If the program uses static linking, it will be very inconvenient to update the program through the network. Once there is a small change anywhere in the program, the entire program will be re-downloaded.

In order to solve the shortcomings of static linking, dynamic linking is introduced. The memory distribution of dynamic linking is as shown in the figure,

Linux 動態(tài)鏈接與靜態(tài)鏈接原來是這么回事?

Multiple programs rely on the same shared object file. There is only one copy of this shared object file on the disk and memory, and no copies will be generated. Simply put, it is not like static linking for those object files that make up the program. Perform linking, wait until the program is about to run, and postpone the linking process until it is run. The dynamic link method makes each module more independent and less coupled during the development process, making it easier for different developers and development organizations to develop and test independently.

How to perform dynamic linking?

Look at the following code:

//?lib.c
#include?

void?func(int?i)?{
???printf("func?%d?\n",?i);
}
//?Program.c
void?func(int?i);

int?main()?{
???func(1);
???return?0;
}

The compilation and running process is as follows:

$?gcc?-fPIC?-shared?-o?lib.so?lib.c
$?gcc?-o?test?Program.c?./lib.so
$?./test
$?func?1

You can generate a dynamic link library through -fPIC and -shared, and then link it to the executable program to run normally.

You can view the segment information of the dynamic link library through the readelf command:

~/test$?readelf?-l?lib.so

Elf?file?type?is?DYN?(Shared?object?file)
Entry?point?0x530
There?are?7?program?headers,?starting?at?offset?64

Program?Headers:
?Type???????????Offset?????????????VirtAddr???????????PhysAddr
????????????????FileSiz????????????MemSiz??????????????Flags??Align
?LOAD???????????0x0000000000000000?0x0000000000000000?0x0000000000000000
????????????????0x00000000000006e4?0x00000000000006e4??R?E????0x200000
?LOAD???????????0x0000000000000e10?0x0000000000200e10?0x0000000000200e10
????????????????0x0000000000000218?0x0000000000000220??RW?????0x200000
?DYNAMIC????????0x0000000000000e20?0x0000000000200e20?0x0000000000200e20
????????????????0x00000000000001c0?0x00000000000001c0??RW?????0x8
?NOTE???????????0x00000000000001c8?0x00000000000001c8?0x00000000000001c8
????????????????0x0000000000000024?0x0000000000000024??R??????0x4
?GNU_EH_FRAME???0x0000000000000644?0x0000000000000644?0x0000000000000644
????????????????0x0000000000000024?0x0000000000000024??R??????0x4
?GNU_STACK??????0x0000000000000000?0x0000000000000000?0x0000000000000000
????????????????0x0000000000000000?0x0000000000000000??RW?????0x10
?GNU_RELRO??????0x0000000000000e10?0x0000000000200e10?0x0000000000200e10
????????????????0x00000000000001f0?0x00000000000001f0??R??????0x1

Section?to?Segment?mapping:
?Segment?Sections...
??00?????.note.gnu.build-id?.gnu.hash?.dynsym?.dynstr?.gnu.version?.gnu.version_r?.rela.dyn?.rela.plt?.init?.plt?.plt.got?.text?.fini?.rodata?.eh_frame_hdr?.eh_frame
??01?????.init_array?.fini_array?.dynamic?.got?.got.plt?.data?.bss
??02?????.dynamic
??03?????.note.gnu.build-id
??04?????.eh_frame_hdr
??05
??06?????.init_array?.fini_array?.dynamic?.got

You can see that the loading address of the dynamic link module starts from 0. 0 is an invalid address. Its loading address will be determined when the program is running and is uncertain at compile time.

Change the program:

//?Program.c
#include?
void?func(int?i);

int?main()?{
???func(1);
???sleep(-1);
???return?0;
}

Run to read maps information:

~/test$?./test?&
[1]?126
~/test$?func?1
cat?/proc/126/maps
7ff2c59f0000-7ff2c5bd7000?r-xp?00000000?00:00?516391?????????????/lib/x86_64-linux-gnu/libc-2.27.so
7ff2c5bd7000-7ff2c5be0000?---p?001e7000?00:00?516391?????????????/lib/x86_64-linux-gnu/libc-2.27.so
7ff2c5be0000-7ff2c5dd7000?---p?000001f0?00:00?516391?????????????/lib/x86_64-linux-gnu/libc-2.27.so
7ff2c5dd7000-7ff2c5ddb000?r--p?001e7000?00:00?516391?????????????/lib/x86_64-linux-gnu/libc-2.27.so
7ff2c5ddb000-7ff2c5ddd000?rw-p?001eb000?00:00?516391?????????????/lib/x86_64-linux-gnu/libc-2.27.so
7ff2c5ddd000-7ff2c5de1000?rw-p?00000000?00:00?0
7ff2c5df0000-7ff2c5df1000?r-xp?00000000?00:00?189022?????????????/mnt/d/wzq/wzq/util/test/lib.so
7ff2c5df1000-7ff2c5df2000?---p?00001000?00:00?189022?????????????/mnt/d/wzq/wzq/util/test/lib.so
7ff2c5df2000-7ff2c5ff0000?---p?00000002?00:00?189022?????????????/mnt/d/wzq/wzq/util/test/lib.so
7ff2c5ff0000-7ff2c5ff1000?r--p?00000000?00:00?189022?????????????/mnt/d/wzq/wzq/util/test/lib.so
7ff2c5ff1000-7ff2c5ff2000?rw-p?00001000?00:00?189022?????????????/mnt/d/wzq/wzq/util/test/lib.so
7ff2c6000000-7ff2c6026000?r-xp?00000000?00:00?516353?????????????/lib/x86_64-linux-gnu/ld-2.27.so
7ff2c6026000-7ff2c6027000?r-xp?00026000?00:00?516353?????????????/lib/x86_64-linux-gnu/ld-2.27.so
7ff2c6227000-7ff2c6228000?r--p?00027000?00:00?516353?????????????/lib/x86_64-linux-gnu/ld-2.27.so
7ff2c6228000-7ff2c6229000?rw-p?00028000?00:00?516353?????????????/lib/x86_64-linux-gnu/ld-2.27.so
7ff2c6229000-7ff2c622a000?rw-p?00000000?00:00?0
7ff2c62e0000-7ff2c62e3000?rw-p?00000000?00:00?0
7ff2c62f0000-7ff2c62f2000?rw-p?00000000?00:00?0
7ff2c6400000-7ff2c6401000?r-xp?00000000?00:00?189023?????????????/mnt/d/wzq/wzq/util/test/test
7ff2c6600000-7ff2c6601000?r--p?00000000?00:00?189023?????????????/mnt/d/wzq/wzq/util/test/test
7ff2c6601000-7ff2c6602000?rw-p?00001000?00:00?189023?????????????/mnt/d/wzq/wzq/util/test/test
7fffee96f000-7fffee990000?rw-p?00000000?00:00?0?????????????????[heap]
7ffff6417000-7ffff6c17000?rw-p?00000000?00:00?0?????????????????[stack]
7ffff729d000-7ffff729e000?r-xp?00000000?00:00?0?????????????????[vdso]

可以看到,整個進程虛擬地址空間中,多出了幾個文件的映射,lib.so和test一樣,它們都是被操作系統(tǒng)用同樣的方法映射到進程的虛擬地址空間,只是它們占據(jù)的虛擬地址和長度不同.

從maps里可以看見里面還有l(wèi)ibc-2.27.so,這是C語言運行庫,還有一個ld-2.27.so,這是Linux下的動態(tài)鏈接器,動態(tài)鏈接器和普通共享對象一樣被映射到進程的地址空間,在系統(tǒng)開始運行test前,會先把控制權交給動態(tài)鏈接器,動態(tài)鏈接器完成所有的動態(tài)鏈接工作后會把控制權交給test,然后執(zhí)行test程序。

當鏈接器將Program.o鏈接成可執(zhí)行文件時,這時候鏈接器必須確定目標文件中所引用的func函數(shù)的性質(zhì),如果是一個定義于其它靜態(tài)目標文件中的函數(shù),那么鏈接器將會按照靜態(tài)鏈接的規(guī)則,將Program.o的func函數(shù)地址進行重定位,如果func是一個定義在某個動態(tài)鏈接共享對象中的函數(shù),那么鏈接器將會將這個符號的引用標記為一個動態(tài)鏈接的符號,不對它進行地址重定位,將這個過程留在裝載時再進行。

動態(tài)鏈接的方式

動態(tài)鏈接有兩種方式:裝載時重定位和地址無關代碼技術。

裝載時重定位:

在鏈接時對所有絕對地址的引用不作重定位,而把這一步推遲到裝載時完成,也叫基址重置,每個指令和數(shù)據(jù)相當于模塊裝載地址是固定的,系統(tǒng)會分配足夠大的空間給裝載模塊,當裝載地址確定后,那指令和數(shù)據(jù)地址自然也就確定了。

然而動態(tài)鏈接模塊被裝載映射到虛擬空間,指令被重定位后對于每個進程來講是不同的,沒有辦法做到同一份指令被多個進程共享,所以指令對不同的進程來說有不同的副本,還是空間浪費,怎么解決這個問題?使用fPIC方法。

地址無關代碼:

指令部分無法在多個進程之間共享,不能節(jié)省內(nèi)存,所以引入了地址無關代碼的技術。我們平時編程過程中可能都見過-fPIC的編譯選項,這個就代表使用了地址無關代碼技術來實現(xiàn)真正的動態(tài)鏈接。

基本思想就是使用GOT(全局偏移表),這是一個指向變量或函數(shù)地址的指針數(shù)組,當指令要訪問變量或者調(diào)用函數(shù)時,會去GOT中找到相應的地址進行間接跳轉(zhuǎn)訪問,每個變量或函數(shù)都對應一個地址,鏈接器在裝載模塊的時候會查找每個變量和函數(shù)的地址,然后填充GOT中的各個項,確保每個指針指向的地址正確。GOT放在數(shù)據(jù)段,所以它可以在模塊裝載時被修改,并且每個進程都可以有獨立的副本,相互不受影響。

tips

?

-fpic和-fPIC的區(qū)別:它們都是地址無關代碼技術,-fpic產(chǎn)生的代碼相對較小較快,但是在某些平臺會有些限制,所以大多數(shù)情況下都是用-fPIC來產(chǎn)生地址無關代碼。

?

-fPIC和-fPIE的區(qū)別:一個作用于共享對象,一個作用于可執(zhí)行文件,一個以地址無關方式編譯的可執(zhí)行文件被稱作地址無關可執(zhí)行文件。

?

-fpie和-fPIE的區(qū)別:類似于-fpic和-fPIC的區(qū)別

延遲綁定技術

在程序剛啟動時動態(tài)鏈接器會尋找并裝載所需要的共享對象,然后進行符號地址尋址重定位等工作,這些工作會減慢程序的啟動速度,如果解決?

使用PLT延遲綁定技術,這里會單獨有一個叫.PLT的段,ELF將 GOT拆分成兩個表.GOT和.GOT.PLT,其中.GOT用來保存全局變量的引用地址,.GOT.PLT用來保存外部函數(shù)的地址,每個外部函數(shù)在PLT中都有一個對應項,在初始化時不會綁定,而是在函數(shù)第一次被用到時才進行綁定,將函數(shù)真實地址與對應表項進行綁定,之后就可以進行間接跳轉(zhuǎn)。

顯式運行時鏈接

支持動態(tài)鏈接的系統(tǒng)往往都支持顯式運行時鏈接,也叫運行時加載,讓程序自己在運行時控制加載的模塊,在需要時加載需要的模塊,在不需要時將其卸載。這種運行時加載方式使得程序的模塊組織變得很靈活,可以用來實現(xiàn)一些諸如插件、驅(qū)動等功能。

通過這四個API可以進行顯式運行時鏈接:

dlopen():打開動態(tài)鏈接庫
dlsym():查找符號
dlerror():錯誤處理
dlclose():關閉動態(tài)鏈接庫

參考這段使用代碼:

#include?
#include?

int?main()?{
???
???void?*handle;
???void?(*f)(int);
???char?*error;

???handle?=?dlopen("./lib.so",?RTLD_NOW);
???if?(handle?==?NULL)?{
???????printf("handle?null?\n");
???????return?-1;
??}
???f?=?dlsym(handle,?"func");
???do?{
???????if?((error?=?dlerror())?!=?NULL)?{
???????????printf("error\n");
???????????break;
??????}
???????f(100);
??}?while?(0);
???dlclose(handle);

???return?0;
}

編譯運行:

$?gcc?-o?test?program.c?-ldl
$?./test
func?100

總結

為什么要進行動態(tài)鏈接?為了解決靜態(tài)鏈接浪費空間和更新困難的缺點。

How to dynamically link? Load-time relocation and address-independent code technology.

Principles of address-independent code technology? Realize indirect jump through GOT segment.

Principles of lazy loading technology? Implement delayed binding and indirect jumps through the PLT segment for external function symbols.

How to do explicit runtime linking? Through the four functions in the header file, the code is as above.

The above is the detailed content of What is the original meaning of dynamic linking and static linking in Linux?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1488
72
How to install Linux alongside Windows (dual boot)? How to install Linux alongside Windows (dual boot)? Jun 18, 2025 am 12:19 AM

The key to installing dual systems in Linux and Windows is partitioning and boot settings. 1. Preparation includes backing up data and compressing existing partitions to make space; 2. Use Ventoy or Rufus to make Linux boot USB disk, recommend Ubuntu; 3. Select "Coexist with other systems" or manually partition during installation (/at least 20GB, /home remaining space, swap optional); 4. Check the installation of third-party drivers to avoid hardware problems; 5. If you do not enter the Grub boot menu after installation, you can use boot-repair to repair the boot or adjust the BIOS startup sequence. As long as the steps are clear and the operation is done properly, the whole process is not complicated.

What Are the Steps to Install Redis on a Linux System? What Are the Steps to Install Redis on a Linux System? Jun 11, 2025 am 12:11 AM

ToinstallRedisonaLinuxsystem,followthesesteps:1)DownloadandextractRedisfromtheofficialGitHubrepository,2)CompileRedisusingthe'make'command,3)InstallRediswith'sudomakeinstall',4)ConfigureRedisbycopyingandeditingtheconfigurationfile,and5)StartRedisusin

How to enable the EPEL (Extra Packages for Enterprise Linux) repository? How to enable the EPEL (Extra Packages for Enterprise Linux) repository? Jun 17, 2025 am 09:15 AM

The key to enabling EPEL repository is to select the correct installation method according to the system version. First, confirm the system type and version, and use the command cat/etc/os-release to obtain information; second, enable EPEL through dnfinstallepel-release on CentOS/RockyLinux, and the 8 and 9 version commands are the same; third, you need to manually download the corresponding version of the .repo file and install it on RHEL; fourth, you can re-import the GPG key when encountering problems. Note that the old version may not be supported, and you can also consider enabling epel-next to obtain the test package. After completing the above steps, use dnfrepolist to verify that the EPEL repository is successfully added.

How to choose a Linux distro for a beginner? How to choose a Linux distro for a beginner? Jun 19, 2025 am 12:09 AM

Newbie users should first clarify their usage requirements when choosing a Linux distribution. 1. Choose Ubuntu or LinuxMint for daily use; programming and development are suitable for Manjaro or Fedora; use Lubuntu and other lightweight systems for old devices; recommend CentOSStream or Debian to learn the underlying principles. 2. Stability is preferred for UbuntuLTS or Debian; you can choose Arch or Manjaro to pursue new features. 3. In terms of community support, Ubuntu and LinuxMint are rich in resources, and Arch documents are technically oriented. 4. In terms of installation difficulty, Ubuntu and LinuxMint are relatively simple, and Arch is suitable for those with basic needs. It is recommended to try it first and then decide.

How to add a new disk to Linux How to add a new disk to Linux Jun 27, 2025 am 12:15 AM

The steps to add a new hard disk to the Linux system are as follows: 1. Confirm that the hard disk is recognized and use lsblk or fdisk-l to check; 2. Use fdisk or parted partitions, such as fdisk/dev/sdb and create and save; 3. Format the partition to a file system, such as mkfs.ext4/dev/sdb1; 4. Use the mount command for temporary mounts, such as mount/dev/sdb1/mnt/data; 5. Modify /etc/fstab to achieve automatic mount on the computer, and test the mount first to ensure correctness. Be sure to confirm data security before operation to avoid hardware connection problems.

Where are system logs located in Linux? Where are system logs located in Linux? Jun 24, 2025 am 12:15 AM

Logs in Linux systems are usually stored in the /var/log directory, which contains a variety of key log files, such as syslog or messages (record system logs), auth.log (record authentication events), kern.log (record kernel messages), dpkg.log or yum.log (record package operations), boot.log (record startup information); log content can be viewed through cat, tail-f or journalctl commands; application logs are often located in subdirectories under /var/log, such as Apache's apache2 or httpd directory, MySQL log files, etc.; at the same time, it is necessary to note that log permissions usually require s

Fixed the failure to upload files in Windows Google Chrome Fixed the failure to upload files in Windows Google Chrome Jul 08, 2025 pm 02:33 PM

Have problems uploading files in Google Chrome? This may be annoying, right? Whether you are attaching documents to emails, sharing images on social media, or submitting important files for work or school, a smooth file upload process is crucial. So, it can be frustrating if your file uploads continue to fail in Chrome on Windows PC. If you're not ready to give up your favorite browser, here are some tips for fixes that can't upload files on Windows Google Chrome 1. Start with Universal Repair Before we learn about any advanced troubleshooting tips, it's best to try some of the basic solutions mentioned below. Troubleshooting Internet connection issues: Internet connection

What is the sudo command and when should I use it? What is the sudo command and when should I use it? Jul 02, 2025 am 12:20 AM

sudo stands for "substituteuserdo" or "superuserdo", allowing users to run commands with permissions of other users (usually root). Its core uses include: 1. Perform system-level operations such as installing software or editing system files; 2. Accessing protected directories or logs; 3. Manage services such as restarting nginx; 4. Modify global settings such as /etc/hosts. When using it, the system will check the /etc/sudoers configuration and verify the user password, provide temporary permissions instead of continuously logging in as root, ensuring security. Best practices include: only when necessary, avoid blindly executing network commands, editing sudoers files with visudo, and considering continuous operations.

See all articles