2013-06-10 25 views
7

Tôi đang làm việc một vài mô-đun hạt nhân Linux và có câu hỏi liên quan đến vấn đề tải vòng tròn.Việc tải biểu tượng đã xuất có bị trì hoãn không?

Mô-đun Lần tải đầu tiên và xuất nhiều ký hiệu cho việc sử dụng mô-đun B hoặc C. Mô-đun B hoặc C sau đó được tải sau đó và các ký hiệu tồn tại để sử dụng.

Tuy nhiên, bây giờ tôi thấy rằng mô-đun A yêu cầu ký hiệu từ mô-đun B hoặc C, nhưng chỉ trong thời gian chạy và không cần thiết để khởi tạo mô-đun. Vì vậy, tất nhiên khi một tải, nó thấy rằng biểu tượng không tồn tại. Tôi thậm chí đã có biểu tượng được đánh dấu là extern trong mô-đun A nhưng điều đó cũng không hoạt động.

Có thể trì hoãn việc tải biểu tượng sau khi mô-đun A đã được tải, mặc dù nó chưa tồn tại cho đến khi B hoặc C đã được tải?

Trả lời

5

Các tình huống như vậy thường được giải quyết bằng cách sử dụng gọi lại.

Giả sử mô-đun A xuất các chức năng để đăng ký/hủy đăng ký cuộc gọi lại. B và/hoặc C sử dụng các chức năng này và cung cấp các callback thích hợp cho A. Khi cần, A kiểm tra nếu các cuộc gọi lại được thiết lập và gọi chúng.

Something như thế này (mà không xử lý lỗi và khóa vì đơn giản):

/* Module A */ 
struct a_ops /* Better to define struct a_ops in a header file */ 
{ 
    void (*needed_func)(void); 
    void (*another_needed_func)(void); 
}; 
... 
struct a_ops ops = { 
    .needed_func = NULL; 
    .another_needed_func = NULL; 
}; 
... 
int a_register_needed_funcs(struct a_ops *a_ops) 
{ 
    ops.needed_func = a_ops->needed_func; 
    ops.another_needed_func = a_ops->another_needed_func; 
} 
EXPORT_SYMBOL(a_register_needed_funcs); 

void a_unregister_needed_funcs() 
{ 
    ops.needed_func = NULL; 
    ops.another_needed_func = NULL; 
} 
EXPORT_SYMBOL(a_unregister_needed_funcs); 

... 
/* Call the specified callbacks when needed: */ 
void do_something(void) 
{ 
    if (ops.needed_func != NULL) { 
     ops.needed_func(); 
    } 
    else { 
      /* the callback is not set, handle this: report error, ignore it or 
      * do something else */ 
      ... 
    } 
} 
... 

/* Modules B and C */ 
/* Their code #includes the file where struct a_ops is defined. 
* The module registers the callbacks, for example, in its init function 
* and unregister in exit function. */ 
... 
static void func(void) 
{ 
    ... 
} 

static void another_func(void) 
{ 
    ... 
} 

struct a_ops my_funcs = { 
    .needed_func = func; 
    .another_needed_func = another_func; 
}; 

int __init my_module_init(void) 
{ 
    ... 
    result = a_register_needed_funcs(&my_funcs); 
    ... 
} 
void __exit my_module_exit(void) 
{ 
    ... 
    a_unregister_needed_funcs(); 
    ... 
} 

này tương tự như tập tin hoạt động và nhiều hoạt động khác gọi lại trong kernel. Giả sử người dùng muốn đọc từ một thiết bị nhân vật được trình điều khiển tùy chỉnh duy trì. Các hạt nhân thích hợp (VFS, để được chính xác) nhận được yêu cầu nhưng không thể xử lý nó chính nó. Nó chuyển tiếp yêu cầu đến trình điều khiển tùy chỉnh đã đăng ký các cuộc gọi lại hoạt động của tệp cho thiết bị đó. Đổi lại, trình điều khiển sử dụng các chức năng được hạt nhân xuất khẩu thích hợp, như cdev_add(), v.v.

1

Nếu bạn biết loại/nguyên mẫu của biểu tượng, hãy thử sử dụng kallsyms_lookup_name() để lấy con trỏ đến biểu tượng mong muốn trong thời gian chạy thay vì liên kết với nó như một biểu tượng bên ngoài (có nghĩa là để bộ nạp tìm kiếm nó khi bạn tải thời gian). Bạn có thể tìm thấy các ví dụ bằng công cụ tìm kiếm yêu thích của mình.

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