sách gpt4 ai đã đi

Xây dựng lại thư viện động khi tham số typedef thay đổi

In lại Tác giả: IT Prince Thời gian cập nhật: 2023-10-29 00:38:14 26 4
mua khóa gpt4 Nike

Giả sử tôi có một cấu trúc C,DynApiArg_t.

định nghĩa kiểu cấu trúc DynApiArg_s {
uint32_t m1;
...
uint32_t mx;
} DynApiArg_t;

Một con trỏ tới cấu trúc này được truyền như một tham số cho hàm nói

khoảng trống DynLibApi(DynApiArg_t *arg)
{
đối số->m1 = 0;
another_fn_in_the_lib(arg->mold); /* Có thể bị sập ở đây. (1) */
}

Có trong các thư viện động libdyn.so ở giữa. API này có sẵn thông qua dlopen/dlsym Quy trình gọi được gọi từ một tệp thực thi.

Nếu thư viện động này được cập nhật lên phiên bản 2, DynApiArg_t Bây giờ có những thành viên mới, chẳng hạn như m2, như được hiển thị bên dưới:

định nghĩa kiểu cấu trúc DynApiArg_s {
uint32_t m1;
OldMbr_t *khuôn;
...
uint32_t mx;
uint32_t m2;
MớiMbr *mnew;
} DynApiArg_t;

Nếu không có sự xây dựng lại hoàn chỉnh dlopen/dlsym Một tệp thực thi hoặc thư viện khác gọi API này, mỗi khi tôi gọi API này, tôi thấy tiến trình bị sập do có sự tham chiếu đến một thành viên nào đó trong cấu trúc. Tôi biết việc truy cập m2 có thể là một vấn đề. Nhưng bạn có thể thấy rằng việc truy cập các thành viên như thế này khuôn Sẽ gây ra sự cố.

định nghĩa void (*fnPtr_t)(DynApiArg_t*);


khoảng trống DynApiCaller(DynApiArg_t *arg)
{
void *libhdl = dlopen("libdyn.so", RTLD_LAZY | RTLD_GLOBAL);
fnPtr_t fptr = dlsym(libhdl, "DynLibApi");
fnptr(arg); /* cuộc gọi thực tế đến API được tải động (2) */
}

Khi gọi API thông qua fnptr, tại dòng được đánh dấu (2), khi truy cập thành viên cũ/hiện có tại (1) (trong v1 của lib, khi DynApiCaller được biên dịch ban đầu), đôi khi có thể có bất kỳ rác nào, thậm chí VÔ GIÁ TRỊ.

Cách chính xác để xử lý các bản cập nhật như vậy mà không phải biên dịch lại hoàn toàn tệp thực thi mỗi khi thư viện phụ thuộc được cập nhật là gì?

Tôi đã thấy các thư viện được đặt tên bằng liên kết tượng trưng, ​​với số phiên bản như libsolid.so.4. Có bất cứ điều gì liên quan đến hệ thống kiểm soát phiên bản này có thể giúp tôi không? Nếu vậy, bạn có thể chỉ cho tôi tài liệu chính xác về những điều này không?

1 Câu trả lời

Có nhiều cách để giải quyết vấn đề này:

  1. Bao gồm phiên bản API trong tên thư viện động.

    Việc sử dụng của bạn dlopen("libfoo.so.4") Còn hơn là dlopen("libfoo.so"). Các phiên bản chính khác nhau của thư viện về cơ bản là độc lập và có thể cùng tồn tại trên cùng một hệ thống; do đó, tên gói của thư viện sẽ là ví dụ:thư viện foo-4. Bạn có thể cài đặt cả hai libfoo.so.4libfoo.so.5. Phiên bản nhỏ hơn, ví dụ: thư viện foo-4.2,Cài đặt libfoo.so.4.2, Và libfoo.so.4 Liên kết tượng trưng đến libfoo.so .4.2.

  2. Ban đầu, hãy xác định cấu trúc với phần đệm bằng không (yêu cầu trong các phiên bản trước của thư viện) và để các phiên bản sau sử dụng lại các trường đệm nhưng vẫn giữ nguyên kích thước cấu trúc.

    <
  3. Sử dụng tên tượng trưng cho phiên bản. Đây là một tiện ích mở rộng của Linux sử dụng dlvsym() .Một thư viện nhị phân chia sẻ duy nhất có thể triển khai nhiều phiên bản của cùng một ký hiệu động.

  4. sử dụng chức năng giải quyếtCác ký hiệu được xác định tại thời điểm tải. Điều này cho phép, ví dụ, các biến thể chức năng được tối ưu hóa được chọn khi chạy cho kiến ​​trúc phần cứng, nhưng dlopen() Phương pháp này không thực sự hữu ích.

  5. Sử dụng cấu trúc để mô tả API thư viện và sử dụng các hàm có phiên bản để lấy/khởi tạo API đó.

    Ví dụ, phiên bản 4 của thư viện của bạn có thể triển khai

     cấu trúc libfoo_api {
    int (*func1)(int arg1, int arg2);
    dữ liệu kép;
    khoảng trống (*func2)(khoảng trống);
    /* ... */
    };

    và chỉ xuất ra một biểu tượng,

     int libfoo_init(struct libfoo_api *const api, const int phiên bản);

    Gọi hàm này sẽ khởi tạo các ký hiệu được hỗ trợ. Giao diện lập trình ứng dụng (API) cấu trúc, giả sử rằng cấu trúc tương ứng với phiên bản đã chỉ định. Thư viện chia sẻ có thể hỗ trợ nhiều phiên bản. Nếu phiên bản nào đó không được hỗ trợ, hệ thống sẽ trả về lỗi.

    Điều này đặc biệt hữu ích cho các giao diện loại plugin (mặc dù _khởi tạo Các hàm có nhiều khả năng gọi các hàm đăng ký hàm do ứng dụng cung cấp hơn là điền vào các cấu trúc), vì một tệp duy nhất có thể chứa nhiều phiên bản của các hàm được tối ưu hóa, được tối ưu hóa cho nhiều kiến ​​trúc phần cứng tương thích (ví dụ: kiến ​​trúc AMD/Intel có hỗ trợ SSE/AVX/AVX2/AVX512 khác nhau).

Lưu ý rằng các chi tiết triển khai ở trên có thể được "ẩn" trong các tệp tiêu đề, giúp mã C thực tế sử dụng thư viện chia sẻ trở nên đơn giản hơn. Nó cũng giúp cho cùng một API hoạt động trên nhiều hệ điều hành, chỉ bằng cách thay đổi các tệp tiêu đề để sử dụng các phương thức hoạt động tốt nhất trên hệ điều hành đó, trong khi vẫn giữ nguyên giao diện C thực tế.

Liên quan đến c - xây dựng lại thư viện động khi tham số typedef thay đổi, chúng tôi tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/45467653/

26 4 0
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com