2013-05-24 44 views
11

Tôi có câu hỏi nhanh về thư viện chia sẻ Windows (DLL) và thư viện chia sẻ Linux (SOs). Tại sao khi bạn tạo một DLL Windows, nó đòi hỏi chương trình máy khách cũng liên kết với một thư viện tĩnh (tệp .lib), nhưng các ứng dụng được tạo trong Linux không yêu cầu bất kỳ liên kết nào chống lại thư viện tĩnh như vậy.Thư viện được chia sẻ: Phương pháp Windows vs Linux

Có liên quan gì đến việc di chuyển mã hay không? Cảm ơn.

+0

Nó được gọi là * thư viện nhập * và các công cụ tồn tại để trích xuất chúng từ các tệp DLL. –

Trả lời

16

Không thực sự với việc di chuyển mã, đó là vấn đề hoàn toàn khác. Đó là về sự khác biệt về kiến ​​trúc:

  • Trong Windows, DLL giống như tệp thực thi (EXE). Sự khác biệt chính giữa EXE và DLL là EXE có một điểm vào (chức năng chính/WinMain) và do đó nó có thể được sử dụng để bắt đầu một quá trình, trong khi các tệp DLL chỉ có thể được nạp vào một quá trình đã tồn tại trước đó. Nhưng hãy xem (1)

  • Trong Linux, aso cũng hoạt động tương tự như một thư viện tĩnh (.a). Sự khác biệt chính là tệp .so có thể được liên kết với một chương trình đang chạy, trong khi tệp .a chỉ có thể được liên kết khi biên dịch chương trình.

Hậu quả của phương pháp này là trong cùng một tệp có thể được sử dụng để tạo và chạy chương trình. Nhưng trong Windows bạn cần một thư viện thích hợp (LIB) để liên kết chương trình. Trên thực tế, lib tương ứng với một DLL thường không có gì hơn tên của các hàm, để đáp ứng mối liên kết và các nhánh để thực hiện việc di chuyển. Nhưng xem (2)

(1) Vâng, các tệp DLL cũng có điểm vào, nhưng nó không được sử dụng làm hàm chính, giống như một số loại móc khởi tạo/kết thúc.

(2) Một số trình liên kết đủ thông minh để có thể, trong một số trường hợp đơn giản, liên kết đến một DLL bằng cách sử dụng chính DLL đó mà không cần tệp LIB bổ sung. Tôi nghĩ rằng ít nhất mối liên kết MinGW có thể làm điều đó.

+0

Cảm ơn bạn đã giải thích kỹ lưỡng. – QAH

+4

Một '.so' là * hoàn toàn * khác với một thư viện tĩnh (' .a'). – duskwuff

+0

@duskwuff: Nó có định dạng khác nhau, nhưng không quá nhiều về hành vi. Aso được thiết kế để hoạt động giống như a .a ngoại trừ việc nó liên kết trong thời gian chạy. Ngay cả độ phân giải biểu tượng và các quy tắc hiển thị gần như giống hệt nhau, sao cho một chương trình có thể được chuyển từ liên kết tĩnh đến liên kết động với mức độ đau tối thiểu. – rodrigo

3

Trong Windows, chương trình máy khách không cần phải liên kết với một thư viện tĩnh để truy cập các chức năng trong một DLL. Liên kết động có thể xảy ra hoàn toàn vào thời gian chạy mà không cần chương trình khách hàng thậm chí còn nhận thức được sự tồn tại của DLL tại thời điểm nó được biên dịch.

Ví dụ, nếu bạn muốn gọi một tên hàm "foo" trong một DLL có tên là "bar.dll", bạn có thể viết mã như thế này:

HINSTANCE hinst = LoadLibrary("bar.dll"); 
FARPROC foo = GetProcAddress(hinst, "foo"); 
foo(); 

Và "foo" và "thanh. dll "có thể dễ dàng có được các giá trị mà chỉ được thiết lập tại thời gian chạy, nói thông qua một tập tin cấu hình hoặc một số đầu vào người dùng khác.

Mục đích của thư viện tĩnh là tự động hóa quy trình tải động này, bằng cách tạo các sơ đồ xuất hiện giống như các hàm thường xuyên theo chương trình khách hàng, nhưng được liên kết với DLL khi chạy. Thông thường liên kết này xảy ra tại thời điểm quá trình khách hàng được tải, nhưng các thư viện cũng có thể được tạo ra sẽ tải và liên kết theo yêu cầu, do đó DLL sẽ không được đưa vào bộ nhớ cho đến khi nó thực sự cần thiết. Đây là thư viện tĩnh xác định khi nào liên kết xảy ra.

Phần lớn, trình biên dịch có thể tự động tạo các thư viện này, vì vậy về mặt kỹ thuật chúng không cần thiết khi chỉ liên kết đến các hàm DLL. Tuy nhiên, một ngoại lệ cho điều này (mà tôi biết) là khi liên kết đến các biến được chia sẻ.

Trong tệp DLL Windows, bạn có thể tạo phân đoạn dữ liệu được chia sẻ với các biến có thể được truy cập bằng bất kỳ quá trình nào đã tải DLL đó. Thông tin về kích thước và kiểu của các biến đó được lưu trữ trong thư viện tĩnh liên quan, và không thể được xác định từ DLL một mình. Để truy cập vào các biến đó, chương trình máy khách phải liên kết với thư viện tĩnh cho DLL đó.

Theo như tôi biết, Thư viện chia sẻ Linux không hỗ trợ khái niệm như vậy.

Cập nhật

Tôi cũng nên đề cập đến rằng trên Windows nó có thể tạo ra một DLL nơi điểm vào chức năng chỉ được xuất khẩu bởi thứ tự (số) chứ không phải là tên. Điều này có thể được coi là một dạng ẩn dữ liệu và thường sẽ được sử dụng khi một người triển khai thực hiện các chức năng nhất định để giữ riêng tư.

Người nào đó có quyền truy cập vào thư viện tĩnh sẽ có thể gọi các hàm đó theo tên, vì thư viện sẽ có các chi tiết liên kết tên hàm với thứ tự thích hợp. Bất cứ ai chỉ có DLL sẽ phải liên kết thủ công với các hàm theo thứ tự hoặc tạo thư viện tĩnh của riêng chúng với tên được tạo sẵn.

+0

Bạn có muốn chia sẻ một số tham chiếu liên quan đến hình thức chia sẻ bộ nhớ này không? –

+0

LoadLibrary + GetProcAddress sẽ là dlopen + dlsym trong Linux, thường được sử dụng để tải "các plugin" và như vậy. – grawity

+1

* "Theo tôi biết, Thư viện chia sẻ Linux không hỗ trợ khái niệm" * - Linux cũng có chúng. Cũng xem phần 'GNU_SHR' trong ELF. – jww

24

Tại sao khi bạn tạo DLL Windows, chương trình máy khách cũng liên kết với thư viện tĩnh (tệp .lib), nhưng ứng dụng được tạo trong Linux không yêu cầu bất kỳ liên kết nào với thư viện tĩnh.

Đây là quyết định thiết kế lịch sử của Microsoft để người liên kết có thể thêm tham chiếu DLL vào tệp thực thi mà không cần phiên bản DLL cụ thể có tại thời gian liên kết. Lý do cho điều này là, luôn có các phiên bản Windows khác nhau, với các phiên bản DLL khác nhau. Cũng tại thời điểm đó Microsoft đã hợp tác với IBM trên OS/2 và kế hoạch là, các chương trình Windows cũng có thể được thực hiện trên OS/2. Vâng, Microsoft đã quyết định "backstab" OS/2, bằng cách tung hệ điều hành cấp chuyên nghiệp của họ, dựa trên hạt nhân NT. Nhưng điều này có nghĩa là, để phát triển bạn muốn các nhà phát triển có thể liên kết với các DLL hệ thống, mà không cần phải có tất cả các biến thể khác nhau của DLL. Thay vào đó, một "mẫu" liên kết động sẽ được sử dụng để tạo cả tệp DLL và tệp thực thi (cả ở định dạng PE), đây là những tệp .lib cụ thể, không phải là thư viện, mà chỉ đơn thuần là biểu tượng và bảng thứ tự (là một thực tế ít được biết đến, nhưng các biểu tượng nhị phân PE có thể được nạp không chỉ bởi một mã định danh chuỗi, mà còn bởi một số nguyên, thứ gọi là thứ tự).

Một hiệu ứng phụ của các số thứ tự là chúng cho phép ẩn các biểu tượng có thể đọc được của con người, để bạn có thể sử dụng DLL chỉ khi bạn biết mối quan hệ hàm → → thứ tự.

Trong Unix truyền thống là, "bạn xây dựng nó trên hệ thống bạn đang đi để chạy nó trên", hoặc "bạn có tất cả các tập tin hệ thống mục tiêu tại chỗ". Vì vậy, không bao giờ có một khuyến khích để thư viện riêng biệt và thông tin liên kết. Về mặt kỹ thuật cũng sẽ làm việc cho các tệp DLL. Các PE có thể xuất một biểu tượng và bảng di chuyển, mà các DLL làm, và một trình liên kết có thể lấy tất cả thông tin mà nó yêu cầu từ đó, tốt thôi.

Nếu bạn ẩn các biểu tượng với các đối tượng chia sẻ Unix, bạn thường làm điều này bằng cách sử dụng một đơn struct với tất cả các con trỏ hàm và chỉ xuất một cá thể liên tục toàn cục của cấu trúc này theo tên. rất nhiều con trỏ không được đặt tên rõ ràng. Bạn có thể làm chính xác như vậy với Windows DLL, mặc dù.

TL; DR: Lý do không phải là kỹ thuật, mà là lý do kỹ thuật, nhưng là quyết định tiếp thị và phân phối.

+0

Câu trả lời hay! Đây sẽ là câu trả lời được chấp nhận. – damphat

Các vấn đề liên quan