การเชื่อมโยงแบบไดนามิก - Vs Linux ของ windows


10

ใน Windows เมื่อฉันรวบรวมรหัส C / C ++ ในโครงการ DLL ใน MSVC ฉันได้รับ 2 ไฟล์:

  1. MyDll.dll
  2. MyDll.lib

ที่เท่าที่ฉันเข้าใจMyDll.libมีชนิดของตารางตัวชี้ที่ระบุตำแหน่งฟังก์ชั่นใน dll เมื่อใช้ dll นี้พูดในไฟล์ exe MyDll.libจะถูกฝังลงในไฟล์ exe ในระหว่างการเชื่อมโยงดังนั้นในขณะรันไทม์มัน "รู้" ซึ่งฟังก์ชั่นตั้งอยู่ในMyDll.dllและสามารถใช้งานได้

แต่ถ้าฉันรวบรวมรหัสเดียวกันภายใต้ Linux ฉันได้รับเพียงไฟล์เดียวMySo.soโดยไม่ MySo.a(เทียบเท่ากับlibไฟล์ใน Linux) ดังนั้นไฟล์ปฏิบัติการภายใต้ Linux รู้ได้อย่างไรว่าฟังก์ชั่นตั้งอยู่ที่ไหนMySo.soถ้าไม่มีอะไรฝังอยู่ในระหว่างการเชื่อมโยง?

คำตอบ:


1

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

MySo.aหากสร้างขึ้นจริง ๆ แล้วจะรวมสัญลักษณ์ที่จะเชื่อมโยงเข้าสู่ไบนารีโดยตรงแทน "ตารางการค้นหาสัญลักษณ์" ที่ใช้บน Windows

คำตอบของ rustyxอธิบายกระบวนการบน Windows ให้ละเอียดกว่าที่เป็นไปได้ เป็นเวลานานแล้วที่ฉันใช้ Windows


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

@yugr เอาส่วนนั้นออกไปฉันก็จับหลอดได้แล้ว
SS Anne

4

ตัวเชื่อมโยง MSVC สามารถเชื่อมโยงวัตถุไฟล์ (.obj) และไลบรารีวัตถุ (.lib) เพื่อสร้าง. EXE หรือ. DLL

เมื่อต้องการเชื่อมโยงกับ DLL กระบวนการใน MSVC จะใช้ไลบรารีการนำเข้าที่เรียกว่า (.LIB) ที่ทำหน้าที่เป็นกาวระหว่างชื่อฟังก์ชัน C และชื่อตารางส่งออก DLL (ใน DLL ฟังก์ชันสามารถส่งออกโดยใช้ชื่อหรือ ตามลำดับ - ส่วนหลังมักใช้สำหรับ API ที่ไม่มีเอกสาร)

อย่างไรก็ตามในกรณีส่วนใหญ่ตารางการส่งออก DLL มีชื่อฟังก์ชันทั้งหมดและทำให้ไลบรารีการนำเข้า (.LIB) มีข้อมูลที่ซ้ำซ้อนส่วนใหญ่ (" ฟังก์ชั่นนำเข้า ABC -> ฟังก์ชันส่งออก ABC " ฯลฯ )
มันเป็นไปได้ที่จะสร้าง. LIB จาก. DLL ที่มีอยู่

ตัวเชื่อมโยงบนแพลตฟอร์มอื่นไม่มี "คุณสมบัติ" นี้และสามารถเชื่อมโยงกับไลบรารีแบบไดนามิกได้โดยตรง


"ตัวเชื่อมโยงบนแพลตฟอร์มอื่นไม่มีคุณสมบัตินี้" - มันง่ายที่จะนำไปใช้ (เช่นImplib.soทำเช่นนี้เพื่อ Linux) เพื่อให้ได้การโหลดล่าช้าและสินค้าอื่น ๆ
yugr

@yugr: นั่นเป็นสาเหตุที่ "คุณสมบัติ" อยู่ในเครื่องหมายคำพูด - ไม่ใช่สิ่งที่คุณต้องการทำและเป็นงานพิเศษที่คุณต้องทำบน Windows
Chris Dodd

1

ความแตกต่างที่คุณจะเห็นมากขึ้นของรายละเอียดการดำเนินงาน - ภายใต้ประทุนทั้ง Linux และ Windows ทำงานในทำนองเดียวกัน - รหัสเรียกฟังก์ชันต้นขั้วที่มีการเชื่อมโยงแบบคงที่ในการปฏิบัติการของคุณและต้นขั้วนี้แล้วโหลด DLL / shlib ถ้าจำเป็น (ในกรณีของความล่าช้า โหลดมิฉะนั้นห้องสมุดมีการโหลดเมื่อโปรแกรมเริ่มต้น) และ (ในสายแรก) แก้ไขสัญลักษณ์ทาง/GetProcAddressdlsym

ความแตกต่างเพียงอย่างเดียวคือบน Linux ฟังก์ชัน stub เหล่านี้ (ซึ่งเรียกว่า PLT stubs) จะถูกสร้างแบบไดนามิกเมื่อคุณเชื่อมโยงแอปของคุณกับ dynamic library (ไลบรารีมีข้อมูลเพียงพอที่จะสร้าง) ในขณะที่ Linux จะถูกสร้างขึ้นเมื่อ DLL เอง สร้างขึ้นใน.libไฟล์แยกต่างหาก

ทั้งสองวิธีมีความคล้ายคลึงกันซึ่งจริง ๆ แล้วเป็นไปได้ที่จะเลียนแบบการนำเข้าไลบรารีของ Windows บน Linux (ดูโครงการImplib.so )


0

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


-3

.dllหรือ.soเป็น libs ที่ใช้ร่วมกัน (เชื่อมโยงในรันไทม์) ขณะที่.aและ.libเป็นห้องสมุดแบบคงที่ (เชื่อมโยงในเวลารวบรวม) นี่ไม่ใช่ความแตกต่างระหว่าง Windows และ Linux

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

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

int example(int x) {
  ...do_something...
}

int ret = example(42);

อย่างไรก็ตามในระดับ asm อาจมีความแตกต่างมากมาย ตัวอย่างเช่นบน x86 callopcode จะถูกดำเนินการและ42จะได้รับบนสแต็ก หรือในบางทะเบียน หรือที่ไหนก็ได้ ไม่มีใครรู้ว่าก่อนจะเขียน dllวิธีการที่จะใช้ หรือว่าโครงการจะต้องการใช้มันเป็นไปได้เขียนด้วยคอมไพเลอร์ (หรือในภาษา!) ซึ่งไม่ได้อยู่ตอนนี้ (หรือมันไม่เป็นที่รู้จักสำหรับนักพัฒนาของ dll)

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

ตามที่คุณเห็นอย่างถูกต้อง Windows ที่กำหนดเองคือการสร้าง dll เรายังสร้างขั้นต่ำ.a/.libด้วย ไลบรารีแบบสแตติกขั้นต่ำนี้เป็นเพียงเครื่องห่อหุ้มสัญลักษณ์ (ฟังก์ชั่น) ของ dll นั้นจะถูกส่งถึงมัน ทำให้การแปลงการโทรระดับ asm ที่ต้องการ

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

ข้อเสียอีกอย่างหนึ่งคือแม้ว่าคุณจะใช้ไลบรารี่แบบไดนามิกคุณต้องรวบรวมกระดาษห่อเล็ก ๆ นี้แบบคงที่

ใน Linux อินเทอร์เฟซแบบไบนารีของ DLLs เป็นมาตรฐานและปฏิบัติตามอนุสัญญา C ดังนั้นไม่.aจำเป็นและมีความเข้ากันได้ของไบนารีระหว่าง libs ที่ใช้ร่วมกันเพื่อแลกเปลี่ยนเราไม่มีข้อได้เปรียบของ microsoft custom


1
โปรดระบุลิงก์พิสูจน์อักษรที่ฟังก์ชันสตับสามารถเปลี่ยนลำดับอาร์กิวเมนต์ ฉันไม่เคยได้ยินเกี่ยวกับเรื่องนี้มาก่อนและยากที่จะเชื่อเนื่องจากว่าค่าใช้จ่ายจะสูงเพียงใด
yugr

@yugr การเรียงลำดับการลงทะเบียน / สแต็กอย่างง่ายไม่ใช่ค่าใช้จ่ายด้านประสิทธิภาพ หากคุณใช้ dll ที่คอมไพล์ด้วย msvc จากไบนารี่ที่คอมไพล์ด้วย msvc แล้วแน่นอนว่าจะไม่เกิดขึ้นมากเกินไป แต่มันก็ทำได้
peterh - Reinstate Monica

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

@yugr stubs สามารถเข้าถึงลายเซ็นฟังก์ชันของ dll ซึ่งทำให้การประมวลผลแบบไม่สำคัญเล็กน้อย
peterh - Reinstate Monica

1
ฉันขอแนะนำให้คุณทำคำตอบของคุณให้สมบูรณ์ด้วยลิงก์เชื่อมโยงไม่กี่ข้อเกี่ยวกับสิ่งที่ไลบรารีนำเข้าทำ
yugr
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.