2013-06-10 7 views
7

मैं कुछ लिनक्स कर्नेल मॉड्यूल काम कर रहा हूं और एक परिपत्र लोडिंग समस्या से संबंधित एक प्रश्न है।निर्यात किए गए प्रतीकों की लोडिंग में देरी हो सकती है?

मॉड्यूल पहले लोड करता है और मॉड्यूल बी या सी के उपयोग के लिए कई प्रतीकों का निर्यात करता है। मॉड्यूल बी या सी बाद में लोड हो जाते हैं और प्रतीक उनके उपयोग के लिए मौजूद होते हैं।

हालांकि, अब मुझे लगता है कि मॉड्यूल ए को मॉड्यूल बी या सी से एक प्रतीक की आवश्यकता है, लेकिन केवल रनटाइम के दौरान, और मॉड्यूल को प्रारंभ करने के लिए आवश्यक नहीं है। तो निश्चित रूप से जब एक भार, यह पता चलता है कि प्रतीक अभी तक मौजूद नहीं है। मुझे मॉड्यूल ए में बाहरी के रूप में चिह्नित प्रतीक भी मिला है लेकिन यह भी काम नहीं करता है।

क्या मॉड्यूल ए लोड होने के बाद प्रतीक के लोडिंग में देरी हो सकती है, हालांकि यह अभी तक बी या सी लोड होने तक मौजूद नहीं है?

उत्तर

5

ऐसी स्थितियों को अक्सर कॉलबैक का उपयोग करके हल किया जाता है।

मान लीजिए मॉड्यूल ए कॉलबैक पंजीकृत/पंजीकरण रद्द करने के लिए कार्यों का निर्यात करता है। बी और/या सी इन कार्यों का उपयोग करते हैं और उचित कॉलबैक प्रदान करते हैं। जब इसकी आवश्यकता होती है, तो कॉलबैक सेट होने पर उन्हें चेक करता है और उन्हें कॉल करता है।

कुछ इस तरह (त्रुटि हैंडलिंग के बिना और सादगी के लिए ताला लगा):

/* 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(); 
    ... 
} 

यह कर्नेल में संचालन और कई अन्य कॉलबैक संचालन फाइल करने के लिए समान है। मान लें कि कोई उपयोगकर्ता एक कस्टम ड्राइवर द्वारा बनाए गए एक वर्ण डिवाइस से कहना चाहता है। कर्नेल उचित (VFS, सटीक होना) अनुरोध प्राप्त करता है लेकिन इसे स्वयं संभाल नहीं सकता है। यह उस कस्टम ड्राइवर के अनुरोध को आगे बढ़ाता है जिसने उस डिवाइस के लिए अपनी फ़ाइल ऑपरेशन कॉलबैक पंजीकृत की है। बदले में, ड्राइवर कर्नेल द्वारा निर्यात किए गए कार्यों का उपयोग करता है, जैसे cdev_add(), आदि

1

यदि आप प्रतीक के प्रकार/प्रोटोटाइप को जानते हैं, तो बाहरी प्रतीक के रूप में इसे जोड़ने के बजाय रनटाइम पर वांछित प्रतीक पर पॉइंटर प्राप्त करने के लिए kallsyms_lookup_name() का उपयोग करने का प्रयास करें (जिसका मतलब लोडर को लोड पर आपके लिए दिखाना है पहर)। उदाहरण आपके पसंदीदा खोज इंजन का उपयोग करके पाया जा सकता है।

संबंधित मुद्दे