it-swarm-vi.com

Làm thế nào để các số SO (đối tượng chia sẻ) hoạt động?

Tôi biết rằng các đối tượng được chia sẻ trong Linux sử dụng "số", cụ thể là các phiên bản khác nhau của đối tượng được chia sẻ được cung cấp các tiện ích mở rộng khác nhau, ví dụ:

  • example.so.1
  • example.so.2

Tôi hiểu ý tưởng là có hai tệp riêng biệt sao cho hai phiên bản của thư viện có thể tồn tại trên một hệ thống (trái ngược với "DLL Hell" trên Windows). Tôi muốn biết làm thế nào điều này hoạt động trong thực tế? Thông thường, tôi thấy rằng example.so thực tế là một liên kết tượng trưng đến example.so.2 Ở đâu .2 là phiên bản mới nhất. Làm thế nào để một ứng dụng tùy thuộc vào phiên bản cũ hơn của example.so xác định chính xác? Có quy định nào về những con số người ta phải sử dụng không? Hay đây chỉ đơn giản là quy ước? Có phải là trường hợp, không giống như trong Windows nơi các nhị phân phần mềm được chuyển giữa các hệ thống, nếu một hệ thống có phiên bản mới hơn của một đối tượng chia sẻ, nó sẽ tự động được liên kết với phiên bản cũ hơn khi biên dịch từ nguồn?

Tôi nghi ngờ điều này có liên quan đến ldconfig nhưng tôi không biết làm thế nào.

127
user119

Bản thân Binaries biết phiên bản nào của thư viện dùng chung mà họ phụ thuộc và yêu cầu cụ thể. Bạn có thể sử dụng ldd để hiển thị các phụ thuộc; của tôi cho ls là:

$ ldd /bin/ls
    linux-gate.so.1 =>  (0xb784e000)
    librt.so.1 => /lib/librt.so.1 (0xb782c000)
    libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
    libc.so.6 => /lib/libc.so.6 (0xb76dc000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
    /lib/ld-linux.so.2 (0xb784f000)
    libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)

Như bạn có thể thấy, nó trỏ đến ví dụ libpthread.so.0, không chỉ libpthread.so.


Lý do cho các liên kết tượng trưng là cho các liên kết. Khi bạn muốn liên kết với libpthread.so trực tiếp, bạn cho gcc cờ -lpthread và nó thêm vào tiền tố lib.so hậu tố tự động. Bạn không thể bảo nó thêm vào .so.0 hậu tố, do đó, liên kết tượng trưng chỉ đến phiên bản mới nhất của lib để tạo điều kiện cho

91
Michael Mrozek

Các số trong các thư viện dùng chung là quy ước được sử dụng trong Linux để xác định API của thư viện. Thông thường định dạng là:

libFOO.so.MAJOR.MINOR

Và như bạn nhận thấy thường có một liên kết tượng trưng từ libFOO.so đến libFOO.so.MAJOR.MINOR. ldconfig chịu trách nhiệm cập nhật liên kết này lên phiên bản mới nhất.

MAJOR thường được tăng lên khi API thay đổi (điểm nhập mới bị xóa hoặc các tham số hoặc loại thay đổi). MINOR thường được tăng lên cho các bản phát hành sửa lỗi hoặc khi các API mới được giới thiệu mà không phá vỡ các API hiện có.

Một cuộc thảo luận rộng rãi hơn có thể được tìm thấy ở đây: Phân tích các thư viện chia sẻ

61
miguel.de.icaza

Các thư viện dùng chung nên được phiên bản theo sơ đồ sau:

blah.so.X.Y.Z

ở đâu

  • X = phát hành ABI không tương thích ngược
  • Y = phát hành ABI tương thích ngược
  • Z = Chỉ thay đổi nội bộ - không thay đổi đối với ABI

Thông thường, bạn chỉ thấy chữ số đầu tiên như hello.so.1 Vì chữ số đầu tiên là thứ duy nhất cần thiết để xác định "phiên bản" của thư viện vì tất cả các chữ số khác đều tương thích ngược.

ldconfig duy trì một bảng các thư viện chia sẻ có sẵn trên một hệ thống và nơi đường dẫn đến thư viện đó tồn tại. Bạn có thể xác minh điều này bằng cách chạy:

ldconfig -p

Khi một gói được xây dựng cho một cái gì đó như Red Hat, các thư viện chia sẻ được gọi ra trong hệ nhị phân sẽ được tra cứu và thêm vào dưới dạng phụ thuộc của gói tại thời điểm xây dựng RPM. Do đó, khi bạn đi cài đặt gói, trình cài đặt sẽ tìm kiếm xem hello.so.1 Có được cài đặt trên hệ thống hay không bằng cách kiểm tra ldconfig.

Bạn có thể thấy sự phụ thuộc của gói bằng cách thực hiện một số thứ như:

rpm -qpR hello.rpm

Hệ thống này (không giống như Windows) cho phép nhiều phiên bản hello.so Được cài đặt trên một hệ thống và được sử dụng bởi các ứng dụng khác nhau cùng một lúc.

25
ascotan

libNAME.so là tên tệp được trình biên dịch/trình liên kết sử dụng khi lần đầu tiên tìm kiếm một thư viện được chỉ định bởi -lNAME. Bên trong tệp thư viện dùng chung là một trường có tên SONAME. Trường này được đặt khi chính thư viện được liên kết đầu tiên thành một đối tượng dùng chung (vì vậy) bởi quá trình xây dựng. SONAME này thực sự là những gì một trình liên kết lưu trữ trong một tệp thực thi tùy thuộc vào đối tượng được chia sẻ đó được liên kết với nó. Thông thường SONAME ở dạng libNAME.so.MAJOR và được thay đổi bất cứ lúc nào thư viện không tương thích với các tệp thực thi hiện có được liên kết với nó và cả hai phiên bản chính của thư viện có thể được cài đặt khi cần (mặc dù chỉ có một phiên bản sẽ được phát triển như libNAME.so) Ngoài ra, để hỗ trợ dễ dàng nâng cấp giữa các phiên bản nhỏ của thư viện, libNAME.so.MAJOR thường là một liên kết đến một tệp như libNAME.so.MAJOR.MINOR. Một phiên bản nhỏ mới có thể được cài đặt và sau khi hoàn thành, liên kết đến phiên bản phụ cũ bị lỗi để chỉ đến phiên bản nhỏ mới ngay lập tức nâng cấp tất cả các thực thi mới để sử dụng thư viện được nâng cấp. Ngoài ra, hãy xem câu trả lời của tôi cho Linux, GNU GCC, ld, tập lệnh phiên bản và định dạng nhị phân ELF - Nó hoạt động như thế nào?

20
penguin359