ความแตกต่างระหว่างไลบรารีแบบคงที่และไลบรารีแบบไดนามิกโดยไม่สนใจว่าตัวเชื่อมโยง/ตัวโหลดใช้งานอย่างไร

ฉันเข้าใจว่าไลบรารีแบบคงที่/ไดนามิกถูกใช้โดยตัวเชื่อมโยง/ตัวโหลดอย่างไร

  1. อย่างไรก็ตาม เหตุใดจึงไม่มีไฟล์ไลบรารีประเภทเดียวที่มาพร้อมกับแฟล็กคอมไพเลอร์ซึ่งระบุว่าควรเชื่อมโยงไลบรารีอย่างไร (คงที่และไดนามิก)
  2. จากข้อเท็จจริงง่ายๆ ที่เรามีไลบรารีแบบคงที่และไดนามิก ฉันถือว่าไฟล์เหล่านี้มีเนื้อหาเฉพาะที่เปิดใช้งานการเชื่อมโยงแบบคงที่และไดนามิกตามลำดับ ใครช่วยอธิบายความแตกต่างระหว่างเนื้อหาของไฟล์สแตติกและไลบรารีที่ใช้ร่วมกันได้บ้าง

person rahul    schedule 04.11.2017    source แหล่งที่มา


คำตอบ (4)


น่าเสียดายที่คำว่า ไลบรารีแบบคงที่ และ ไลบรารีแบบไดนามิก เป็นทั้งสองรูปแบบ ไลบรารี ADJECTIVE เพราะมันทำให้โปรแกรมเมอร์คิดว่าพวกเขาแสดงถึงตัวแปรตลอดเวลา ของสิ่งเดียวกันโดยพื้นฐานแล้ว สิ่งนี้เกือบจะทำให้เข้าใจผิดพอๆ กับความคิดที่ว่าสนามแบดมินตันและศาลฎีกาโดยพื้นฐานแล้วเป็นสิ่งเดียวกัน ในความเป็นจริง มันทำให้เข้าใจผิดมากกว่ามาก เนื่องจากไม่มีใครทนทุกข์ทรมานจากการคิดว่าสนามแบดมินตันและศาลฎีกาโดยพื้นฐานแล้วคือสิ่งเดียวกัน

ใครช่วยอธิบายความแตกต่างระหว่างเนื้อหาของไฟล์สแตติกและไลบรารีที่ใช้ร่วมกันได้บ้าง

ลองใช้ตัวอย่าง หากต้องการตอบโต้กับสนามแบดมินตัน / หมอกศาลฎีกา ฉันจะใช้คำศัพท์ทางเทคนิคที่แม่นยำยิ่งขึ้น แทนที่จะเป็น ไลบรารีแบบคงที่ ฉันจะพูดว่า ar เก็บถาวร และแทนที่จะเป็น ไลบรารีแบบไดนามิก ฉันจะพูดว่า วัตถุที่ใช้ร่วมกันแบบไดนามิก หรือเรียกสั้น ๆ ว่า DSO

ไฟล์เก็บถาวร ar คืออะไร

ฉันจะสร้างไฟล์เก็บถาวร ar โดยเริ่มจากสามไฟล์นี้:

foo.c

#include <stdio.h>

void foo(void)
{
    puts("foo");
}

บาร์.ซี

#include <stdio.h>

void bar(void)
{
    puts("bar");
}

limerick.txt

There once was a young lady named bright
Whose speed was much faster than light
She set out one day
In a relative way
And returned on the previous night.

ฉันจะรวบรวมซอร์ส C ทั้งสองนั้นเป็นไฟล์อ็อบเจ็กต์ Position Independent:

$ gcc -c -Wall -fPIC foo.c
$ gcc -c -Wall -fPIC bar.c

ไม่จำเป็นต้องมีไฟล์อ็อบเจ็กต์ที่กำหนดไว้สำหรับไฟล์เก็บถาวร ar ที่จะคอมไพล์ด้วย -fPIC ฉันแค่ต้องการให้สิ่งเหล่านี้รวบรวมแบบนั้น

จากนั้น ฉันจะสร้างไฟล์เก็บถาวร ar ชื่อ libsundry.a ที่มีไฟล์อ็อบเจ็กต์ foo.o และ bar.o บวก limerick.txt:

$ ar rcs libsundry.a foo.o bar.o limerick.txt

แน่นอนว่าไฟล์เก็บถาวร ar ถูกสร้างขึ้นด้วย ar ซึ่งเป็นไฟล์เก็บถาวรวัตถุประสงค์ทั่วไปของ GNU ดังนั้น มันไม่ได้ถูกสร้างโดยตัวเชื่อมโยง ไม่มีการเชื่อมโยงเกิดขึ้น ต่อไปนี้คือวิธีที่ ar รายงานเนื้อหาของไฟล์เก็บถาวร:

$ ar -t libsundry.a 
foo.o
bar.o
limerick.txt

นี่คือลักษณะของโคลงในไฟล์เก็บถาวร:

$ rm limerick.txt
$ ar x libsundry.a limerick.txt; cat limerick.txt
There once was a young lady named bright
Whose speed was much faster than light
She set out one day
In a relative way
And returned on the previous night.

ถาม. การใส่ไฟล์อ็อบเจ็กต์สองไฟล์และ ASCII limerick ลงในไฟล์เก็บถาวร ar เดียวกันจะมีประโยชน์อะไร

ก. เพื่อแสดงให้เห็นว่าฉันทำได้ เพื่อแสดงว่าไฟล์เก็บถาวร ar เป็นเพียงถุงบรรจุไฟล์

มาดูกันว่า file มีประโยชน์อย่างไรจาก libsundry.a.

$ file libsundry.a 
libsundry.a: current ar archive

ตอนนี้ ผมจะเขียนโปรแกรมสองสามโปรแกรมที่ใช้ libsundry.a ในการเชื่อมโยง

fooprog.c

extern void foo(void);

int main(void)
{
    foo();
    return 0;
}

คอมไพล์ ลิงก์ และรันอันนั้น:

$ gcc -c -Wall fooprog.c
$ gcc -o fooprog fooprog.o -L. -lsundry
$ ./fooprog 
foo

นั่นมันดอรี่ตัวใหญ่ เห็นได้ชัดว่าตัวเชื่อมโยงไม่ได้ใส่ใจกับการมีอยู่ของ ASCII limerick ใน libsundry.a

เหตุผลก็คือผู้ลิงก์ไม่ได้พยายามลิงก์ limerick.txt เข้ากับโปรแกรมด้วยซ้ำ มาทำการเชื่อมโยงอีกครั้ง คราวนี้มาพร้อมกับตัวเลือกการวินิจฉัยที่จะแสดงให้เราเห็นว่าไฟล์อินพุตใดบ้างที่ลิงก์อยู่:

$ gcc -o fooprog fooprog.o -L. -lsundry -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o
fooprog.o
(./libsundry.a)foo.o
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

มีไลบรารีเริ่มต้นและไฟล์อ็อบเจ็กต์จำนวนมาก แต่ไฟล์อ็อบเจ็กต์เดียวที่ เรา สร้างขึ้นที่ตัวเชื่อมโยงใช้คือ:

fooprog.o
(./libsundry.a)foo.o

ทั้งหมดที่ลิงเกอร์ทำกับ ./libsundry.a คือนำ foo.o ออกจากกระเป๋าและเชื่อมโยงมันในโปรแกรม หลังจากลิงก์ fooprog.o เข้ากับโปรแกรมแล้ว จำเป็นต้องค้นหาคำจำกัดความของ foo มันมองเข้าไปในกระเป๋า พบคำจำกัดความใน foo.o จึงนำ foo.o ออกจากกระเป๋าและเชื่อมโยงเข้ากับโปรแกรม ในการเชื่อมโยง fooprog,

gcc -o fooprog fooprog.o -L. -lsundry

เป็นการเชื่อมโยงเดียวกันกับ:

$ gcc -o fooprog fooprog.o foo.o

file พูดอะไรเกี่ยวกับ fooprog

$ file fooprog
fooprog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), \
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, \
for GNU/Linux 2.6.32, BuildID[sha1]=32525dce7adf18604b2eb5af7065091c9111c16e,
not stripped

นี่คือโปรแกรมที่สองของฉัน:

foobarprog.c

extern void foo(void);
extern void bar(void);

int main(void)
{
    foo();
    bar();
    return 0;
}

คอมไพล์ ลิงก์ และรัน:

$ gcc -c -Wall foobarprog.c
$ gcc -o foobarprog foobarprog.o -L. -lsundry
$ ./foobarprog 
foo
bar

และนี่คือการเชื่อมโยงอีกครั้งกับ -trace:

$ gcc -o foobarprog foobarprog.o -L. -lsundry -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o
foobarprog.o
(./libsundry.a)foo.o
(./libsundry.a)bar.o
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

ดังนั้นในครั้งนี้ ไฟล์อ็อบเจ็กต์ของเราที่ตัวลิงก์ใช้คือ:

foobarprog.o
(./libsundry.a)foo.o
(./libsundry.a)bar.o

หลังจากลิงก์ foobarprog.o เข้ากับโปรแกรมแล้ว จำเป็นต้องค้นหาคำจำกัดความของ foo และ bar มันมองเข้าไปในกระเป๋า พบคำจำกัดความตามลำดับใน foo.o และ bar.o ดังนั้นจึงนำมันออกจากกระเป๋าและเชื่อมโยงเข้ากับโปรแกรม ในการเชื่อมโยง foobarprog

gcc -o foobarprog foobarprog.o -L. -lsundry

เป็นการเชื่อมโยงเดียวกันกับ:

$ gcc -o foobarprog foobarprog.o foo.o bar.o

สรุปทั้งหมดนั้น.. ไฟล์เก็บถาวร ar เป็นเพียงถุงบรรจุไฟล์ คุณสามารถใช้ไฟล์เก็บถาวร ar เพื่อเสนอไฟล์ อ็อบเจ็กต์ จำนวนหนึ่งให้กับผู้ลิงก์ เพื่อเลือกไฟล์ที่ต้องการสำหรับการเชื่อมโยงต่อไป มันจะนำไฟล์อ็อบเจ็กต์เหล่านั้นออกจากกระเป๋าและเชื่อมโยงเข้ากับไฟล์เอาท์พุต มันไม่มีประโยชน์อย่างอื่นสำหรับกระเป๋าอย่างแน่นอน กระเป๋าไม่ได้มีส่วนช่วยในการเชื่อมโยงเลย

กระเป๋าช่วยให้ชีวิตของคุณง่ายขึ้นเล็กน้อยโดยช่วยให้คุณไม่ต้องรู้ว่าไฟล์อ็อบเจ็กต์ใดที่คุณต้องการสำหรับการเชื่อมโยงโดยเฉพาะ คุณเพียงแค่ต้องรู้ว่า: พวกเขาอยู่ในกระเป๋าใบนั้น

DSO คืออะไร

มาทำอันหนึ่งกัน

foobar.c

extern void foo(void);
extern void bar(void);

void foobar(void)
{
    foo();
    bar();
}

เราจะรวบรวมไฟล์ต้นฉบับใหม่นี้:

$ gcc -c -Wall -fPIC foobar.c

จากนั้นสร้าง DSO โดยใช้ foobar.o และนำ libsundry.a กลับมาใช้ใหม่

$ gcc -shared -o libfoobar.so foobar.o -L. -lsundry -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbeginS.o
foobar.o
(./libsundry.a)foo.o
(./libsundry.a)bar.o
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/usr/lib/gcc/x86_64-linux-gnu/5/crtendS.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

นั่นทำให้ DSO libfoobar.so หมายเหตุ: DSO ถูกสร้างขึ้นโดยตัวเชื่อมโยง มีการเชื่อมโยงเช่นเดียวกับโปรแกรมที่ถูกเชื่อมโยง การเชื่อมโยงของ libfoopar.so ดูคล้ายกับการเชื่อมโยงของ foobarprog มาก แต่การเพิ่มตัวเลือก -shared จะสั่งให้ตัวเชื่อมโยงสร้าง DSO แทนที่จะเป็นโปรแกรม ที่นี่เราจะเห็นว่าไฟล์อ็อบเจ็กต์ของเราที่ใช้โดยการเชื่อมโยงคือ:

foobar.o
(./libsundry.a)foo.o
(./libsundry.a)bar.o

ar ไม่เข้าใจ DSO เลย:

$ ar -t libfoobar.so 
ar: libfoobar.so: File format not recognised

แต่ file ทำ:

$ file libfoobar.so 
libfoobar.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), \
dynamically linked, BuildID[sha1]=16747713db620e5ef14753334fea52e71fb3c5c8, \
not stripped

ตอนนี้ถ้าเราเชื่อมโยง foobarprog ใหม่โดยใช้ libfoobar.so แทน libsundry.a:

$ gcc -o foobarprog foobarprog.o -L. -lfoobar -Wl,-trace,--rpath=$(pwd)
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o
foobarprog.o
-lfoobar (./libfoobar.so)
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so)
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

ที่เราเห็น

foobarprog.o
-lfoobar (./libfoobar.so)

ว่า ./libfoobar.so ตัวมันเอง ถูกเชื่อมโยงอยู่ ไม่ใช่ไฟล์อ็อบเจ็กต์บางไฟล์ "อยู่ข้างใน" ไม่มีไฟล์อ็อบเจ็กต์อยู่ข้างใน และสิ่งนี้มีส่วนทำให้เกิดการเชื่อมโยงได้อย่างไร สามารถเห็นได้จากการพึ่งพาแบบไดนามิกของโปรแกรม:

$ ldd foobarprog
    linux-vdso.so.1 =>  (0x00007ffca47fb000)
    libfoobar.so => /home/imk/develop/so/scrap/libfoobar.so (0x00007fb050eeb000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb050afd000)
    /lib64/ld-linux-x86-64.so.2 (0x000055d8119f0000)

โปรแกรมออกมาพร้อมการพึ่งพารันไทม์ใน libfoobar.so นั่นคือสิ่งที่การเชื่อมโยง DSO ทำ เราจะเห็นได้ว่าการพึ่งพารันไทม์นี้เป็นไปตามที่พอใจ ดังนั้นโปรแกรมจะทำงาน:

$ ./foobarprog
foo
bar

เหมือนเมื่อก่อน

ความจริงที่ว่า DSO และโปรแกรมซึ่งต่างจากไฟล์เก็บถาวร ar ต่างก็เป็นผลิตภัณฑ์ของตัวเชื่อมโยง แสดงให้เห็นว่า DSO และโปรแกรม เป็น ตัวแปรของสิ่งเดียวกันโดยพื้นฐานแล้ว เอาต์พุต file ก็แนะนำเช่นกัน DSO และโปรแกรมเป็นทั้งไบนารีของ ELF ที่ตัวโหลด OS สามารถแมปลงในพื้นที่ที่อยู่ของกระบวนการได้ ไม่ใช่แค่ถุงใส่ไฟล์ ไฟล์เก็บถาวร ar ไม่ใช่ไบนารีของ ELF ใดๆ

ความแตกต่างระหว่างไฟล์ ELF ประเภทโปรแกรมและ ELF ที่ไม่ใช่ประเภทโปรแกรมอยู่ที่ค่าที่แตกต่างกันที่ตัวเชื่อมโยงเขียนลงในโครงสร้าง ELF Header และโครงสร้าง Program Headers ของรูปแบบไฟล์ ELF ความแตกต่างเหล่านี้แนะนำให้ตัวโหลด OS เริ่มต้นกระบวนการใหม่เมื่อโหลดไฟล์ ELF ประเภทโปรแกรม และเพิ่มกระบวนการที่อยู่ระหว่างการสร้างเมื่อโหลดไฟล์ ELF ที่ไม่ใช่โปรแกรม ดังนั้น DSO ที่ไม่ใช่โปรแกรมจึงถูกแมปเข้ากับกระบวนการของโปรแกรมหลัก ความจริงที่ว่าโปรแกรมเริ่มต้นกระบวนการใหม่ต้องการให้โปรแกรมต้องมีจุดเริ่มต้นเดียวซึ่งระบบปฏิบัติการจะผ่านการควบคุม: จุดเริ่มต้นนั้นเป็นฟังก์ชัน main บังคับในโปรแกรม C หรือ C++ ในทางกลับกัน DSO ที่ไม่ใช่โปรแกรมไม่จำเป็นต้องมีจุดเริ่มต้นบังคับเพียงจุดเดียว สามารถป้อนผ่านฟังก์ชันส่วนกลางใดๆ ที่ส่งออกโดยการเรียกใช้ฟังก์ชันจากโปรแกรมหลัก

แต่จากมุมมองของโครงสร้างไฟล์และเนื้อหา DSO และโปรแกรมก็คล้ายกันมาก เป็นไฟล์ที่สามารถเป็นส่วนประกอบของกระบวนการได้ โปรแกรมจะต้องเป็นส่วนประกอบเริ่มต้น DSO สามารถเป็นองค์ประกอบรองได้

ยังคงเป็นเรื่องปกติสำหรับความแตกต่างเพิ่มเติมที่ต้องทำ: DSO จะต้องประกอบด้วยโค้ดที่ย้ายตำแหน่งได้ทั้งหมด (เนื่องจากไม่รู้ว่า ณ เวลาลิงก์ที่ตัวโหลดอาจจำเป็นต้องวางไว้ในพื้นที่ที่อยู่ของกระบวนการ) ในขณะที่โปรแกรมประกอบด้วยโค้ดที่สมบูรณ์ โหลดด้วยที่อยู่เดียวกันเสมอ แต่ในความเป็นจริง มันค่อนข้างเป็นไปได้ที่จะเชื่อมโยง โปรแกรม ที่สามารถย้ายตำแหน่งได้:

$ gcc -pie -o foobarprog foobarprog.o -L. -lfoobar -Wl,--rpath=$(pwd)

นั่นคือสิ่งที่ -pie (การดำเนินการตามตำแหน่งอิสระ) ทำที่นี่ แล้ว:

$ file foobarprog
foobarprog: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), ....

file จะบอกว่า foobarprog เป็น DSO ซึ่งก็คือ แม้ว่ามันจะยังยังคงเป็นโปรแกรมอยู่:

$ ./foobarprog
foo
bar

และโปรแกรมปฏิบัติการ PIE กำลังได้รับความนิยม ใน Debian 9 และอนุพันธ์ distros (Ubuntu 17.04...) GCC toolchain จะสร้างโปรแกรม PIE ตามค่าเริ่มต้น

หากคุณต้องการความรู้โดยละเอียดเกี่ยวกับรูปแบบไฟล์ ar และ ELF นี่คือ รายละเอียดของ ar รูปแบบ และนี่คือรายละเอียดของรูปแบบ ELF

เหตุใดจึงไม่มีไฟล์ไลบรารีประเภทเดียวที่มาพร้อมกับแฟล็กคอมไพเลอร์ซึ่งระบุว่าควรเชื่อมโยงไลบรารีอย่างไร (คงที่และไดนามิก)

ตัวเลือกระหว่างการเชื่อมโยงแบบไดนามิกและแบบคงที่สามารถควบคุมได้อย่างสมบูรณ์ด้วยตัวเลือกการเชื่อมโยงบรรทัดคำสั่ง ดังนั้นจึงไม่จำเป็นต้องละทิ้งไฟล์เก็บถาวร ar หรือ DSO หรือสร้างไลบรารีประเภทอื่นเพื่อให้บรรลุเป้าหมายนี้ หากตัวเชื่อมโยงไม่สามารถใช้ไฟล์เก็บถาวร ar ได้อย่างที่เป็นอยู่ นั่นอาจเป็นความไม่สะดวกอย่างมาก และแน่นอนว่าถ้าตัวเชื่อมโยงไม่สามารถเชื่อมโยง DSO ได้ เราก็จะกลับไปสู่ยุคหินของระบบปฏิบัติการ

person Mike Kinghan    schedule 05.11.2017
comment
สุดยอดคำตอบ!! ทักทาย! - person Zack Zhu; 12.03.2020

เพราะมันเป็นสิ่งที่แตกต่างอย่างสิ้นเชิง ไลบรารีแบบคงที่เป็นเพียงคอลเลกชันของโค้ดอ็อบเจ็กต์ที่สร้างโดยคอมไพเลอร์ ไลบรารีแบบไดนามิกมีการเชื่อมโยง

person user207421    schedule 04.11.2017

  1. รูปแบบของไดนามิกไลบรารีที่โหลด ณ รันไทม์ถูกกำหนดโดยผู้เขียนระบบปฏิบัติการ รูปแบบของไลบรารีแบบคงที่ถูกกำหนดโดยผู้เขียนห่วงโซ่เครื่องมือ บ่อยครั้งที่มีการทับซ้อนกันระหว่างคลาสของโปรแกรมเมอร์เหล่านั้น แต่พวกเขามักจะชอบที่จะแยกข้อกังวลออกไป
  2. ตัวโหลดรันไทม์จำเป็นต้องทราบขนาดของรูปภาพที่จะโหลด บางทีขนาดสแต็กและเซ็กเมนต์ข้อมูลบางส่วน รวมถึงชื่อและจุดเข้าใช้งานของฟังก์ชันใน DLL ตัวเชื่อมโยงจำเป็นต้องรู้มากขึ้นเกี่ยวกับแต่ละออบเจ็กต์ (ฟังก์ชัน/ข้อมูล) ที่เก็บถาวรในไลบรารีแบบคงที่ สิ่งต่างๆ เช่น ลายเซ็นฟังก์ชัน ชนิดข้อมูล ขนาดของสิ่งต่าง ๆ การเริ่มต้น ขอบเขตการเข้าถึง

ระบบปฏิบัติการและกลุ่มเครื่องมือทุกรายการมีข้อกำหนดเฉพาะและประวัติการแก้ไขของตัวเอง ดังนั้นจึงเป็นไปไม่ได้ที่จะระบุเค้าโครงไฟล์ที่แน่นอนสำหรับทั้งหมดที่นี่ โปรดดูรายละเอียดในเอกสารระบบปฏิบัติการและห่วงโซ่เครื่องมือ

person jwdonahue    schedule 04.11.2017

ไลบรารีที่แชร์ได้มีแนวโน้มที่จะถูกคอมไพล์เป็นโค้ดที่ไม่ขึ้นกับตำแหน่ง นั่นหมายความว่า การถ่ายโอนการควบคุมใช้การกำหนดที่อยู่โดยสัมพันธ์กับพีซี เนื่องจากอาจถูกแมปไปยังตำแหน่งที่แตกต่างกันในพื้นที่ที่อยู่ของโปรแกรมไคลเอนต์ที่แตกต่างกัน

ไลบรารีที่แชร์ได้ควรมีการแบ่งแยกที่ชัดเจนระหว่างโค้ด+ข้อมูลแบบอ่านอย่างเดียว กับข้อมูลที่อ่าน/เขียน วิธีนี้จึงต้องโหลดสำเนาของส่วนที่อ่านอย่างเดียวเพียงชุดเดียวลงในหน่วยความจำสำหรับกระบวนการไคลเอ็นต์ทั้งหมด

หากโปรแกรมไคลเอนต์ A อ้างถึงไลบรารี B และ C ในขณะที่ไลบรารี B อ้างอิงถึง C ด้วย คุณต้องแน่ใจว่าทุกอย่างถูกสร้างขึ้นด้วยการตั้งค่าความสามารถในการแชร์ที่สอดคล้องกัน ตัวอย่างเช่น หาก C ถูกสร้างขึ้นในเวอร์ชันที่แชร์ได้และไม่สามารถแชร์ได้ และ B ถูกสร้างขึ้นมาให้สามารถแชร์กับเวอร์ชัน C ที่แชร์ได้ ดังนั้น A จะต้องถูกสร้างขึ้นโดยเทียบกับเวอร์ชันที่แชร์ได้ของทั้ง B และ C หากพยายามใช้เวอร์ชันที่ไม่สามารถแชร์ได้ เวอร์ชัน C ซึ่งอาจนำไปสู่ปัญหาในการสร้าง เนื่องจากความขัดแย้งกับเวอร์ชัน C ที่แชร์ได้ซึ่ง B ใช้อยู่

เอกสารนี้โดย Ulrich Drepper (อดีตผู้ดูแลไลบรารี GNU libc) ให้รายละเอียดเพิ่มเติม มากกว่าที่คุณอยากรู้เกี่ยวกับไลบรารีที่แชร์ได้

person Lawrence D'Oliveiro    schedule 04.11.2017