क्या कर्नेल का एक मुख्य () कार्य है? [बन्द है]


52

मैं डिवाइस ड्राइवर और कर्नेल प्रोग्रामिंग सीख रहा हूं। जोनाथन कॉर्बेट की पुस्तक के अनुसार, main()डिवाइस ड्राइवरों में कोई फ़ंक्शन नहीं है ।

तो मैं दो सवाल:

  • हमें main()डिवाइस ड्राइवरों में फ़ंक्शन की आवश्यकता क्यों नहीं है ?
  • क्या कर्नेल अपने आप में एक main()फ़ंक्शन है?

क्या कोई मुझे ये समझा सकता है?


1
यहाँ भी एक ही उपयोगकर्ता द्वारा पूछा गया: stackoverflow.com/q/18266063/827263
कीथ थॉम्पसन

@KeithThompson ... हां ... सिर्फ इसलिए कि मुझे जवाब नहीं मिला कि मैं क्या चाहता हूं इसलिए मैंने यहां पूछा।
कोई

@Shadur ... वैसे भी अब यह बंद करने के बारे में है ... और मुझे लगता है कि विस्थापित करने के लिए विशेषाधिकार प्राप्त नहीं है ...
किसी

इसे दूसरे तरीके से बंद कर दिया जाना चाहिए था, इस पर बहुत कुछ देखा गया है :-)
Ciro Santilli 新疆 the the the 法轮功

जवाबों:


82

उपयोगकर्ता अंतरिक्ष कार्यक्रमों में, main()उस प्रोग्राम का प्रवेश बिंदु है जिसे बाइनरी निष्पादित होने पर libc initialization कोड द्वारा बुलाया जाता है । कर्नेल कोड में libc पर भरोसा करने की लक्जरी नहीं है, क्योंकि libc मेमोरी आवंटन, I / O, प्रक्रिया प्रबंधन आदि के लिए कर्नेल syscall इंटरफ़ेस पर निर्भर करता है।

उस ने कहा, main()कर्नेल कोड के बराबर है start_kernel(), जो कर्नेल छवि को लोड करने के बाद बूटलोडर द्वारा कहा जाता है , इसे मेमोरी और सेटअप आवश्यक हार्डवेयर और मेमोरी पेजिंग में विघटित करता है। start_kernel()सिस्टम सेटअप के बहुमत को निष्पादित करता है और अंततः init प्रक्रिया को जन्म देता है।

लिनक्स कर्नेल मॉड्यूल में प्रवेश बिंदु एक इनिट फ़ंक्शन है जो module_init()मैक्रो को कॉल करके कर्नेल के साथ पंजीकृत है । पंजीकृत मॉड्यूल इनिट फ़ंक्शन को कर्नेल स्टार्टअप के दौरान फ़ंक्शन के माध्यम से कर्नेल कोड कहा जाता हैdo_initcalls()


11
mainसी। में विधि के वास्तविक उद्देश्य को पहचानने के लिए धन्यवाद (यह एक सभी आमतौर पर गलत धारणा है कि ओएस एक सीधा कॉल करता है main, जो कि मामला नहीं है और उदाहरण के लिए सी ++ में भी कम मामला है।) I ' अगर मैं सिर्फ उसके लिए कर सकता हूँ तो आप एक और उत्थान देंगे।
बजे एक CVn

1
@Thomas ... इस उत्कृष्ट उत्तर के लिए धन्यवाद ....
कोई

17

कर्नेल में mainफ़ंक्शन नहीं होता है । mainC भाषा की एक अवधारणा है। कर्नेल C और असेंबली में लिखा जाता है। कर्नेल का प्रवेश कोड असेंबली द्वारा लिखा गया है।

बूट अनुक्रम इस प्रकार है:

  1. BIOS आमतौर पर बूट ब्लॉक डिवाइस से बूट लोडर लोड करता है। एक लोकप्रिय बूट लोडर अभी ग्रब है।
  2. ग्रब एक प्रारंभिक रूट डिवाइस ( initrd) के साथ, संभव में कर्नेल छवि को लोड करता है । फिर किसी पते पर कोड निष्पादित किया जाता है।
  3. कर्नेल छवि में कुछ कर्नेल मॉड्यूल हैं, उदाहरण के लिए: फाइलसिस्टम मॉड्यूल, डिवाइस ड्राइवर। कर्नेल छवि रूट फाइल सिस्टम को माउंट करने के लिए फाइलसिस्टम मॉड्यूल का उपयोग करती है। अब कर्नेल डिस्क से सभी कर्नेल मॉड्यूल को लोड और चला सकते हैं।
  4. कर्नेल आरंभीकरण कार्य चलाता है। उदाहरण के लिए: पीसीआई बस को पार करें और सभी पीसीआई उपकरणों को ढूंढें, सभी डिवाइस ड्राइवरों को इनिशियलाइज़ करें।
  5. अंत में कर्नेल प्रक्रिया 0 बनाता है और प्रक्रिया 1 ( initप्रक्रिया), सीपीयू के संदर्भ को रिंग 0 से रिंग 3 तक स्विच करता है, और init प्रक्रिया शुरू करता है (प्रक्रिया आईडी 1 है)। अब कर्नेल बूट समाप्त हो गया है!
  6. initकार्यक्रम सभी init स्क्रिप्ट चलाता है। सभी सेवाएं शुरू कर दी हैं। शैल कहा जाता है। उपयोगकर्ता लॉगिन कर सकते हैं।

mainसमारोह एक सी समारोह है। वास्तव में मुख्य विधि सी कार्यक्रमों का प्रवेश बिंदु नहीं है। C रनटाइम पहले कई फ़ंक्शन को कॉल करता है main। जीसीसी की एक विस्तारित विशेषता है: निर्माणकर्ता। "कंस्ट्रक्टर" घोषित किए गए कार्यों को पहले कहा जाता है main

उदाहरण के लिए:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \
} 

यह मैक्रो qemu प्रोजेक्ट से है।


मुख्य विधि एसी विधि है। आमतौर पर मुख्य विधि सी प्रोग्राम की प्रविष्टि नहीं है। सी रनटाइम ने मुख्य विधि से पहले कई तरीकों को बुलाया है।
एडवर्ड शेन

खैर, बायोस आमतौर पर एक बूट लोडर लोड करता है, और वह बूट लोडर एक कर्नेल छवि (और संभवतः एक initrd) को लोड करता है। कर्नेल का कोड कर्नेल छवि में होता है, initrd में नहीं
स्टीफन चेज़लस

जीसीसी की एक विस्तारित विशेषता है: निर्माणकर्ता। विधि घोषणा "कंस्ट्रक्टर" को मुख्य विधि से पहले कहा जाता है। उदाहरण के लिए: / * इसका उपयोग सीधे नहीं किया जाना चाहिए। इसके बजाय ब्लॉक_इनिट आदि का उपयोग करें। * / #define मॉड्यूल_init (फ़ंक्शन, प्रकार) \ static शून्य _attribute __ ((निर्माता)) do_qemu_init ## फ़ंक्शन (शून्य) {\ register_module_init (फ़ंक्शन, प्रकार); \}
एडवर्ड शेन

1
initrd.img नहीं है कर्नेल छवि। यह बूट पर कर्नेल द्वारा लोड किए गए मॉड्यूल का एक सेट है। कर्नेल छवियों में आमतौर पर "vmlinuz" से शुरू होने वाले नाम होते हैं, लेकिन डिस्ट्रो से डिस्ट्रो तक भिन्न होते हैं।
गोल्डीलॉक्स

3
यह उत्तर "सब कुछ एक पीसी / लिनक्स / i86 है" से भरा है और यह इस तरह से बूट करता है और कर्नेल इस तरह से है ... हर कोई क्यों सोचता है कि यह दुनिया में एकमात्र संभव तरीका है?
जेन्स

9

वास्तविक से सुरक्षित मोड में स्विच करने के लिए सिस्टम तैयार करने के लिए मेहराब / x86 / बूट / main.c में एक मुख्य () फ़ंक्शन है, लेकिन अन्य आर्किटेक्चर में ऐसा कोड नहीं है। एक अच्छा अवलोकन है कि x86 प्लेटफॉर्म पर लिनक्स कर्नेल 2.6.x का बूटिंग कैसे काम करता है। यह वास्तव में इसे पढ़ने लायक है।

दस्तावेज़ के अनुसार HOWTO लिनक्स कर्नेल विकास करते हैं , लिनक्स कर्नेल है

एक फ्रीस्टैंडिंग सी पर्यावरण, मानक सी लाइब्रेरी पर निर्भरता नहीं है, इसलिए सी मानक के कुछ हिस्से समर्थित नहीं हैं।

C मानक BTW के अनुसार इसका क्या मतलब है

यह कार्यान्वयन-परिभाषित है कि क्या एक फ्रीस्टैंडिंग वातावरण में एक कार्यक्रम को एक 'मुख्य' फ़ंक्शन को परिभाषित करना आवश्यक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.