Tệp DLL và LIB - cái gì và tại sao?


214

Tôi biết rất ít về DLL và LIB ngoài việc chúng chứa mã quan trọng cần thiết để chương trình chạy đúng - các thư viện. Nhưng tại sao trình biên dịch tạo ra chúng cả? Sẽ không dễ dàng hơn nếu chỉ bao gồm tất cả các mã trong một tệp thực thi? Và sự khác biệt giữa DLL và LIB là gì?


Câu trả lời:


296

Có thư viện tĩnh (LIB) và thư viện động (DLL) - nhưng lưu ý rằng tệp .LIB có thể là thư viện tĩnh (chứa tệp đối tượng) hoặc nhập thư viện (chứa ký hiệu để cho phép trình liên kết liên kết với DLL).

Thư viện được sử dụng vì bạn có thể có mã mà bạn muốn sử dụng trong nhiều chương trình. Ví dụ: nếu bạn viết một hàm đếm số ký tự trong một chuỗi, hàm đó sẽ hữu ích trong nhiều chương trình. Khi bạn làm cho hàm đó hoạt động chính xác, bạn không muốn phải biên dịch lại mã mỗi khi bạn sử dụng nó, vì vậy bạn đặt mã thực thi cho hàm đó vào thư viện và trình liên kết có thể trích xuất và chèn mã đã biên dịch vào chương trình của bạn . Thư viện tĩnh đôi khi được gọi là 'lưu trữ' vì lý do này.

Các thư viện động tiến thêm một bước này. Có vẻ lãng phí khi có nhiều bản sao của các chức năng thư viện chiếm không gian trong mỗi chương trình. Tại sao tất cả họ không thể chia sẻ một bản sao của chức năng? Đây là những gì các thư viện động dành cho. Thay vì xây dựng mã thư viện vào chương trình của bạn khi nó được biên dịch, nó có thể được chạy bằng cách ánh xạ nó vào chương trình của bạn khi nó được tải vào bộ nhớ. Nhiều chương trình chạy cùng lúc sử dụng các chức năng giống nhau đều có thể chia sẻ một bản sao, tiết kiệm bộ nhớ. Trong thực tế, bạn chỉ có thể tải các thư viện động khi cần thiết, tùy thuộc vào đường dẫn thông qua mã của bạn. Không có điểm nào trong việc máy in thường xuyên chiếm bộ nhớ nếu bạn không thực hiện bất kỳ in ấn nào. Mặt khác, điều này có nghĩa là bạn phải có một bản sao của thư viện động được cài đặt trên mỗi máy mà chương trình của bạn chạy.

Ví dụ, hầu hết mọi chương trình được viết bằng 'C' sẽ cần các hàm từ thư viện gọi là thư viện thời gian chạy 'C, mặc dù ít chương trình sẽ cần tất cả các hàm. Thời gian chạy C có cả phiên bản tĩnh và động, vì vậy bạn có thể xác định phiên bản nào chương trình của bạn sử dụng tùy thuộc vào nhu cầu cụ thể.


80
Hóa ra .LIBcác tệp có thể là thư viện tĩnh (chứa tệp đối tượng) hoặc nhập thư viện (chứa các ký hiệu để cho phép trình liên kết liên kết đến một DLL). Tôi đang tự hỏi tại sao lại như vậy.
Lumi

2
lời giải thích hay! Mã được chia sẻ và dữ liệu (theo mặc định) không được chia sẻ giữa (các) ứng dụng tiêu thụ một DLL.
mox

4
@Lumi: Điểm tốt. Về mặt DLL chúng tôi có hai loại liên kết. Liên kết ngầm , khi chúng tôi có một .libtệp được cung cấp bởi người tạo DLL cùng với các tiêu đề thích hợp; đây .libchỉ là một mô tả của DLL mục tiêu, nó chứa địa chỉ, điểm vào, v.v. nhưng không có mã. Điều này .libphải được chuyển đến linker. Cái thứ hai là liên kết rõ ràng khi chúng ta sử dụng DLL bằng cách tải thủ công với LoadLibrarychức năng. Trong loại này, chúng tôi không cần .libtệp đó , nhưng chúng tôi phải nỗ lực một chút để tìm xuất khẩu DLL, địa chỉ của chúng và gọi các hàm này thông qua các con trỏ.
itachi

37

Một khía cạnh khác là bảo mật (obfuscation). Khi một đoạn mã được trích xuất từ ​​ứng dụng chính và đưa vào Thư viện liên kết động "tách biệt", việc tấn công, phân tích (kỹ sư đảo ngược) mã sẽ dễ dàng hơn vì nó đã bị cô lập. Khi cùng một đoạn mã được giữ trong Thư viện LIB, nó là một phần của ứng dụng đích đã được biên dịch (được liên kết) và do đó khó phân tách (phân biệt) đoạn mã đó với phần còn lại của các nhị phân đích.


Các khía cạnh bảo mật là mới đối với tôi. Liệu lý do trên có đúng trong trường hợp ứng dụng C # gọi dll C ++ không được quản lý không?
Martin

1
Nhưng LIB cũng bị cô lập, phải không? Vì vậy, một Attacker chỉ có thể phân tích LIB. Hay đó là một kịch bản phổ biến mà LIB không thể truy cập công khai?
Nick Russler

8
LIB cũng bị "cô lập", theo như quá trình biên dịch có liên quan, nhưng một khi trình liên kết đặt các phần lại với nhau, LIB là một phần của EXE và không thể phân biệt được với mã của riêng bạn.
mox

17

Một lý do quan trọng để tạo DLL / LIB thay vì chỉ biên dịch mã thành tệp thực thi là sử dụng lại và di chuyển. Ứng dụng Java hoặc .NET trung bình (ví dụ) rất có thể sẽ sử dụng một số thư viện của bên thứ 3 (hoặc khung). Việc biên dịch dựa vào thư viện dựng sẵn sẽ dễ dàng và nhanh hơn nhiều so với việc phải biên dịch tất cả mã của bên thứ 3 vào ứng dụng của bạn. Biên dịch mã của bạn vào các thư viện cũng khuyến khích thực hành thiết kế tốt, ví dụ như thiết kế các lớp của bạn sẽ được sử dụng trong các loại ứng dụng khác nhau.


7

DLL là một thư viện các hàm được chia sẻ giữa các chương trình thực thi khác. Chỉ cần nhìn vào thư mục windows / system32 của bạn và bạn sẽ tìm thấy hàng tá chúng. Khi chương trình của bạn tạo một DLL, nó cũng thường tạo một tệp lib để chương trình ứng dụng * .exe có thể giải quyết các ký hiệu được khai báo trong DLL.

.Lib là một thư viện các hàm được liên kết tĩnh với một chương trình - chúng KHÔNG được chia sẻ bởi các chương trình khác. Mỗi chương trình liên kết với tệp * .lib có tất cả mã trong tệp đó. Nếu bạn có hai chương trình A.exe và B.exe liên kết với C.lib thì mỗi A và B đều chứa mã trong C.lib.

Cách bạn tạo DLL và lib phụ thuộc vào trình biên dịch bạn sử dụng. Mỗi trình biên dịch làm điều đó khác nhau.


4

Một sự khác biệt khác nằm ở hiệu suất.

Vì DLL được tải trong thời gian chạy bởi .exe (s), .exe (s) và DLL hoạt động với khái niệm bộ nhớ dùng chung và do đó hiệu suất thấp tương đối với liên kết tĩnh.

Mặt khác, .lib là mã được liên kết tĩnh tại thời gian biên dịch thành mọi quy trình yêu cầu. Do đó, .exe (s) sẽ có bộ nhớ đơn, do đó làm tăng hiệu suất của quá trình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.