वास्तव में एक फ़ाइल खोलने से क्या होता है?


266

सभी प्रोग्रामिंग भाषाओं में (जो मैं कम से कम उपयोग करता हूं), आपको पढ़ने या लिखने से पहले एक फ़ाइल खोलनी होगी।

लेकिन यह खुला ऑपरेशन वास्तव में क्या करता है?

विशिष्ट कार्यों के लिए मैनुअल पृष्ठ वास्तव में आपको इसके अलावा कुछ नहीं बताते हैं 'पढ़ने / लिखने के लिए एक फ़ाइल खोलता है':

http://www.cplusplus.com/reference/cstdio/fopen/

https://docs.python.org/3/library/functions.html#open

जाहिर है, फ़ंक्शन के उपयोग के माध्यम से आप यह बता सकते हैं कि इसमें किसी प्रकार की वस्तु का निर्माण शामिल है जो एक फ़ाइल तक पहुंचने की सुविधा प्रदान करता है।

इसे लगाने का एक और तरीका होगा, अगर मैं एक openफ़ंक्शन को लागू करने के लिए हूं, तो लिनक्स पर क्या करना होगा?


13
इस सवाल का संपादन Cऔर लिनक्स पर ध्यान केंद्रित करने के लिए ; चूंकि लिनक्स और विंडोज क्या करते हैं। अन्यथा, यह थोड़ा व्यापक है। इसके अलावा, किसी भी उच्च स्तरीय भाषा को सिस्टम के लिए या तो C एपीआई या कॉल करने के लिए C को संकलित करने के लिए समाप्त करना होगा, इसलिए "C" के स्तर पर छोड़ते हुए इसे Least Common Denominator पर रखा जाएगा।
जॉर्ज स्टॉकर

1
यह उल्लेख नहीं करने के लिए कि सभी प्रोग्रामिंग भाषाओं में यह सुविधा नहीं है, या यह एक ऐसी सुविधा है जो पर्यावरण पर अत्यधिक निर्भर है। इन दिनों बेशक, दुर्लभ है, लेकिन आज तक फ़ाइल हैंडलिंग एएनएसआई फोर्थ का एक पूरी तरह से वैकल्पिक हिस्सा है, और अतीत में कुछ कार्यान्वयन में भी मौजूद नहीं था।

जवाबों:


184

लगभग हर उच्च-स्तरीय भाषा में, फ़ाइल खोलने वाला फ़ंक्शन संबंधित कर्नेल सिस्टम कॉल के चारों ओर एक आवरण होता है। यह अन्य फैंसी सामान भी कर सकता है, लेकिन समकालीन ऑपरेटिंग सिस्टम में, फ़ाइल खोलना हमेशा कर्नेल के माध्यम से जाना चाहिए।

यही कारण है कि fopenलाइब्रेरी फ़ंक्शन के तर्क , या पायथन के सिस्टम कॉल openके तर्कों को बारीकी से देखा जाता open(2)है।

फ़ाइल को खोलने के अलावा, इन कार्यों को आमतौर पर एक बफर सेट किया जाता है जिसका परिणाम पढ़ने / लिखने के संचालन के साथ उपयोग किया जाएगा। इस बफ़र का उद्देश्य यह सुनिश्चित करना है कि जब भी आप एन बाइट्स पढ़ना चाहते हैं, तो संबंधित लाइब्रेरी कॉल एन बाइट्स को वापस कर देगी, भले ही अंतर्निहित सिस्टम कॉल पर कॉल कम वापस आए।

मैं वास्तव में अपने स्वयं के कार्य को लागू करने में दिलचस्पी नहीं रखता हूं; बस यह समझने में कि नरक क्या चल रहा है ... 'भाषा से परे' अगर आपको पसंद है।

यूनिक्स जैसे ऑपरेटिंग सिस्टम में, एक open"फ़ाइल डिस्क्रिप्टर" को वापस करने के लिए एक सफल कॉल जो उपयोगकर्ता प्रक्रिया के संदर्भ में केवल एक पूर्णांक है। इस डिस्क्रिप्टर को परिणामस्वरूप खोली गई फ़ाइल के साथ इंटरैक्ट करने वाले किसी भी कॉल में पास कर दिया जाता है, और closeउस पर कॉल करने के बाद , डिस्क्रिप्टर अमान्य हो जाता है।

यह नोट करना महत्वपूर्ण है कि कॉल openएक सत्यापन बिंदु की तरह काम करता है जिस पर विभिन्न जांच की जाती हैं। यदि सभी शर्तों को पूरा नहीं किया जाता है, तो कॉल -1डिस्क्रिप्टर के बजाय वापस आने में विफल रहता है , और जिस तरह की त्रुटि का संकेत दिया गया है errno। आवश्यक जांच हैं:

  • चाहे फ़ाइल मौजूद हो;
  • क्या कॉलिंग प्रक्रिया को निर्दिष्ट मोड में इस फ़ाइल को खोलने का विशेषाधिकार प्राप्त है। यह कॉल की प्रक्रिया के संबंधित आईडी के लिए फ़ाइल अनुमतियों, मालिक आईडी और समूह आईडी के मिलान से निर्धारित होता है।

कर्नेल के संदर्भ में, प्रक्रिया के फ़ाइल डिस्क्रिप्टर और भौतिक रूप से खोली गई फ़ाइलों के बीच किसी प्रकार का मानचित्रण होना चाहिए। डिस्क्रिप्टर पर मैप की गई आंतरिक डेटा संरचना में अभी तक एक और बफ़र हो सकता है जो ब्लॉक-आधारित डिवाइसेस, या एक आंतरिक पॉइंटर से संबंधित है जो वर्तमान पढ़ने / लिखने की स्थिति की ओर इशारा करता है।


2
यह ध्यान देने योग्य है कि यूनिक्स की तरह OSes में, इन-कर्नेल संरचना फ़ाइल डिस्क्रिप्टर को मैप किया जाता है, इसे "ओपन फाइल विवरण" कहा जाता है। इसलिए एफडी को कर्नेल ओएफडी में संसाधित किया जाता है। प्रलेखन को समझने के लिए यह महत्वपूर्ण है। उदाहरण के लिए, man dup2एक ओपन फाइल डिस्क्रिप्टर (जो एक एफडी है जो ओपन होता है) और एक ओपन फाइल डिस्क्रिप्शन (एक OFD) के बीच सूक्ष्मता को देखें और जांचें ।
रॉडरिगो

1
हाँ, अनुमतियाँ खुले समय पर जाँच की जाती हैं। आप कर्नेल के "ओपन" कार्यान्वयन के लिए स्रोत को जा सकते हैं और पढ़ सकते हैं: lxr.free-electrons.com/source/fs/open.c। हालांकि यह विशिष्ट फ़ाइल सिस्टम ड्राइवर के लिए अधिकांश काम को दर्शाता है
pjc50

1
(ext2 सिस्टम पर यह निर्देशिका प्रविष्टियों को पढ़ने के लिए पहचानना शामिल करेगा कि किस इनोड में मेटाडेटा है, फिर उस इनोड को इनोड कैश में लोड करना है। ध्यान दें कि "/ proc" और "/ sys" जैसे छद्म-स्तर हो सकते हैं जो मनमाना काम कर सकते हैं। जब आप कोई फ़ाइल खोलते हैं)
pjc50

1
ध्यान दें कि फ़ाइल खुली है - कि फ़ाइल मौजूद है, कि आपके पास अनुमति है - व्यवहार में, पर्याप्त नहीं है। फ़ाइल गायब हो सकती है, या इसकी अनुमति आपके पैरों के नीचे बदल सकती है। कुछ फ़ाइल सिस्टम इसे रोकने का प्रयास करते हैं, लेकिन जब तक आपका OS नेटवर्क स्टोरेज का समर्थन करता है, तब तक इसे रोकना असंभव है (एक ओएस "घबराहट" कर सकता है यदि स्थानीय फाइल सिस्टम गलत व्यवहार करता है और उचित है: ऐसा तब होता है जब कोई नेटवर्क शेयर नहीं करता है एक व्यवहार्य ओएस)। वे चेक फ़ाइल ओपन में भी किए जाते हैं , लेकिन (प्रभावी रूप से) अन्य सभी फ़ाइल एक्सेस पर भी किए जाने चाहिए।
यक्क - एडम नेवेरुमोंट

2
तालों के मूल्यांकन और / या निर्माण को न भूलें। ये साझा किए जा सकते हैं, या अनन्य हो सकते हैं और पूरी फ़ाइल, या इसके केवल एक हिस्से को प्रभावित कर सकते हैं।
थिंकडे नोव

83

मेरा सुझाव है कि आप सिस्टम कॉल के सरलीकृत संस्करण के माध्यमopen() से इस गाइड पर एक नज़र डालें । यह निम्नलिखित कोड स्निपेट का उपयोग करता है, जो एक फ़ाइल खोलने पर पर्दे के पीछे क्या होता है, इसका प्रतिनिधि है।

0  int sys_open(const char *filename, int flags, int mode) {
1      char *tmp = getname(filename);
2      int fd = get_unused_fd();
3      struct file *f = filp_open(tmp, flags, mode);
4      fd_install(fd, f);
5      putname(tmp);
6      return fd;
7  }

संक्षेप में, यहां बताया गया है कि कोड क्या करता है, लाइन से लाइन:

  1. कर्नेल नियंत्रित मेमोरी के एक ब्लॉक को आवंटित करें और उपयोगकर्ता द्वारा नियंत्रित मेमोरी से फ़ाइलनाम को इसमें कॉपी करें।
  2. एक अप्रयुक्त फ़ाइल डिस्क्रिप्टर चुनें, जिसे आप वर्तमान में खुली फ़ाइलों की बढ़ती सूची में पूर्णांक सूचकांक के रूप में सोच सकते हैं। प्रत्येक प्रक्रिया की अपनी एक ऐसी सूची होती है, हालांकि इसे कर्नेल द्वारा बनाए रखा जाता है; आपका कोड इसे सीधे एक्सेस नहीं कर सकता। सूची में एक प्रविष्टि में जो भी जानकारी होती है, अंतर्निहित फाइल सिस्टम डिस्क से बाइट्स खींचने के लिए उपयोग करेगा, जैसे कि इनकोड संख्या, प्रक्रिया अनुमतियाँ, खुले झंडे, और इसी तरह।
  3. filp_openसमारोह कार्यान्वयन है

    struct file *filp_open(const char *filename, int flags, int mode) {
            struct nameidata nd;
            open_namei(filename, flags, mode, &nd);
            return dentry_open(nd.dentry, nd.mnt, flags);
    }

    जो दो काम करता है:

    1. फ़ाइल नाम या पथ जिसे आमतौर पर फ़ाइल सिस्टम का उपयोग किया जाता है, के अंदर (या आम तौर पर, जो भी फाइलनाम या पथ में पारित किया गया था) को देखने के लिए फाइल सिस्टम का उपयोग करें।
    2. struct fileइनोड के बारे में आवश्यक जानकारी के साथ बनाएँ और इसे वापस करें। यह संरचना उस खुली फ़ाइलों की सूची में प्रविष्टि बन जाती है जिसका मैंने पहले उल्लेख किया था।
  4. स्टोर ("इंस्टॉल") खुली फ़ाइलों की प्रक्रिया की सूची में लौटाया गया ढांचा।

  5. आवंटित कर्नेल नियंत्रित मेमोरी के ब्लॉक को मुक्त करें।
  6. फ़ाइल वर्णनकर्ता, जो तब की तरह फ़ाइल आपरेशन कार्यों के लिए पारित किया जा सकता लौटें read(), write()और close()। इनमें से प्रत्येक कर्नेल को नियंत्रण सौंप देगा, जो प्रक्रिया की सूची में संबंधित फ़ाइल पॉइंटर को देखने के लिए फ़ाइल डिस्क्रिप्टर का उपयोग कर सकता है, और वास्तव में रीडिंग, राइटिंग या क्लोज़िंग करने के लिए उस फ़ाइल पॉइंटर में जानकारी का उपयोग कर सकता है।

यदि आप महत्वाकांक्षी महसूस कर रहे हैं, तो आप इस सरलीकृत उदाहरण की तुलना open()लिनक्स कर्नेल में सिस्टम कॉल के कार्यान्वयन से कर सकते हैं , जिसे एक फ़ंक्शन कहा जाता है do_sys_open()। आपको समानताएं खोजने में कोई परेशानी नहीं होनी चाहिए।


बेशक, यह केवल "शीर्ष परत" है क्या होता है जब आप कॉल करते हैं open()- या अधिक सटीक रूप से, यह कर्नेल कोड का उच्चतम-स्तरीय टुकड़ा है जो फ़ाइल खोलने की प्रक्रिया में लगाया जाता है। एक उच्च-स्तरीय प्रोग्रामिंग भाषा इसके ऊपर अतिरिक्त परतें जोड़ सकती है। बहुत कुछ है जो निचले स्तरों पर चलता है। ( समझाने के लिए रुस्लान और pjc50 को धन्यवाद ।) मोटे तौर पर, ऊपर से नीचे तक:

  • open_namei()और dentry_open()फाइल सिस्टम कोड, जो कर्नेल का भी हिस्सा है, को मेटाडेटा और फ़ाइलों और निर्देशिकाओं के लिए सामग्री तक पहुँचाने के लिए आह्वान करता है। फाइल सिस्टम डिस्क से कच्चे बाइट्स पढ़ता है और फ़ाइलों और निर्देशिकाओं का एक वृक्ष के रूप में उन बाइट पैटर्न व्याख्या करता है।
  • फाइलसिस्टम ड्राइव से उन कच्चे बाइट्स को प्राप्त करने के लिए फिर से कर्नेल के ब्लॉक डिवाइस परत का उपयोग करता है । (मजेदार तथ्य: लिनक्स आपको ब्लॉक डिवाइस लेयर का उपयोग करके /dev/sdaऔर इस तरह से कच्चा डेटा एक्सेस करने देता है ।)
  • ब्लॉक डिवाइस परत एक स्टोरेज डिवाइस ड्राइवर, जो कि कर्नेल कोड भी है, को मशीन कोड में "रीड सेक्टर X" जैसे व्यक्तिगत इनपुट / आउटपुट निर्देशों जैसे मध्यम-स्तरीय निर्देश से अनुवाद करने के लिए आमंत्रित करता है । आईडीई , (एस) एटीए , एससीएसआई , फायरवायर , और इसी तरह, विभिन्न संचार मानकों के अनुरूप कई प्रकार के स्टोरेज डिवाइस ड्राइवर हैं, जो एक ड्राइव का उपयोग कर सकते हैं। (ध्यान दें कि नामकरण एक गड़बड़ है।)
  • I / O निर्देश भौतिक ड्राइव पर जाने वाले तार पर विद्युत संकेतों को भेजने और प्राप्त करने के लिए प्रोसेसर चिप और मदरबोर्ड नियंत्रक की अंतर्निहित क्षमताओं का उपयोग करते हैं। यह हार्डवेयर है, सॉफ्टवेयर नहीं।
  • तार के दूसरे छोर पर, डिस्क के फर्मवेयर (एम्बेडेड कंट्रोल कोड) प्लेटों को स्पिन करने और सिर (एचडीडी) को स्थानांतरित करने के लिए विद्युत संकेतों की व्याख्या करता है, या एक फ्लैश रोम सेल (एसएसडी), या जो भी आवश्यक हो डेटा को एक्सेस करने के लिए पढ़ता है। उस प्रकार का स्टोरेज डिवाइस।

यह कैशिंग के कारण कुछ गलत भी हो सकता है । :-P गंभीरता से, कई विवरण हैं जो मैंने छोड़ दिए हैं - एक व्यक्ति (मुझे नहीं) यह वर्णन करने के लिए कि यह प्रक्रिया कैसे काम करती है, कई किताबें लिख सकती हैं। लेकिन यह आपको एक विचार देना चाहिए।


67

आप जिस भी फाइल सिस्टम या ऑपरेटिंग सिस्टम के बारे में बात करना चाहते हैं, वह मेरे द्वारा ठीक है। अच्छा!


एक ZX स्पेक्ट्रम पर, एक LOADकमांड को इनिशियलाइज़ करने से सिस्टम को एक तंग लूप में डाल दिया जाएगा, ऑडियो इन लाइन को पढ़ना।

स्टार्ट-ऑफ डेटा को एक स्थिर टोन द्वारा इंगित किया जाता है, और उसके बाद लंबी / छोटी दालों का एक क्रम चलता है, जहां एक बाइनरी के लिए एक शॉर्ट पल्स होता है 0और बाइनरी के लिए एक लंबा होता है 1( https://en.wikipedia.org/ wiki / ZX_Spectrum_software )। तंग लोड लूप बिट्स को इकट्ठा करता है जब तक कि यह बाइट (8 बिट्स) भरता है, इसे मेमोरी में संग्रहीत करता है, मेमोरी पॉइंटर को बढ़ाता है, फिर अधिक बिट्स के लिए स्कैन करने के लिए वापस लूप करता है।

आमतौर पर, एक लोडर जो पहली चीज पढ़ता है वह एक छोटा, निश्चित प्रारूप हैडर होता है , जो कम से कम बाइट्स की अपेक्षा करता है, और संभवतः अतिरिक्त जानकारी जैसे फ़ाइल नाम, फ़ाइल प्रकार और लोडिंग पता दर्शाता है। इस छोटे हेडर को पढ़ने के बाद, प्रोग्राम यह तय कर सकता है कि डेटा के मुख्य थोक को लोड करना जारी रखना है, या लोडिंग रूटीन से बाहर निकलें और उपयोगकर्ता के लिए एक उपयुक्त संदेश प्रदर्शित करें।

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


इस उत्तर पर थोड़ा पृष्ठभूमि

वर्णित प्रक्रिया एक नियमित ऑडियो टेप से डेटा लोड करती है - इसलिए ऑडियो को स्कैन करने की आवश्यकता है (यह एक मानक प्लग से टेप रिकॉर्डर से जुड़ा है)। एक LOADकमांड तकनीकी रूप से openएक फ़ाइल के समान है - लेकिन यह शारीरिक रूप से वास्तव में फ़ाइल को लोड करने के लिए बंधा हुआ है । ऐसा इसलिए है क्योंकि टेप रिकॉर्डर कंप्यूटर द्वारा नियंत्रित नहीं है, और आप (सफलतापूर्वक) एक फ़ाइल नहीं खोल सकते हैं, लेकिन इसे लोड नहीं कर सकते हैं।

"तंग लूप" का उल्लेख किया गया है क्योंकि (1) सीपीयू, एक Z80-A (यदि मेमोरी कार्य करता है), वास्तव में धीमा था: 3.5 मेगाहर्ट्ज, और (2) स्पेक्ट्रम में कोई आंतरिक घड़ी नहीं थी! इसका मतलब है कि इसे हर राज्य के लिए टी-स्टेट्स (निर्देश समय) की सही गणना करनी थी । एक। अनुदेश। उस लूप के अंदर, बस सटीक बीप टाइमिंग बनाए रखने के लिए।
सौभाग्य से, उस कम सीपीयू की गति का विशिष्ट लाभ था कि आप कागज के एक टुकड़े पर चक्रों की संख्या की गणना कर सकते थे, और इस प्रकार वास्तविक दुनिया का समय जो वे लेंगे।


10
@ बेलवर्गर: हाँ ठीक है। लेकिन यह एक उचित सवाल है (मेरा मतलब है)। मैंने "बहुत व्यापक" के रूप में बंद करने के लिए मतदान किया, और मेरा जवाब यह बताने के लिए है कि प्रश्न वास्तव में कितना व्यापक है।
usr2564301

8
मुझे लगता है कि आप उत्तर को बहुत ज्यादा बढ़ा रहे हैं। ZX स्पेक्ट्रम में OPEN कमांड थी, और यह LOAD से बिल्कुल अलग थी। और समझना कठिन है।
रॉडरिगो

3
मैं प्रश्न को बंद करने पर भी असहमत हूं, लेकिन मुझे वास्तव में आपका जवाब पसंद है।
एनजो फेरबर

23
हालाँकि मैंने अपने प्रश्न को लाइनक्स / विंडोज़ ओएस तक सीमित रखने के लिए इसे खुला रखने के प्रयास में संपादित किया, यह उत्तर पूरी तरह से मान्य और उपयोगी है। जैसा कि मेरे प्रश्न में कहा गया है, मैं अपना काम करने के लिए किसी चीज को लागू करने या अन्य लोगों को प्राप्त करने के लिए नहीं देख रहा हूं, मैं सीखना चाहता हूं। सीखने के लिए आपको 'बड़े' सवाल पूछने चाहिए। अगर हम एसओ पर 'बहुत व्यापक' होने के लिए लगातार सवाल उठाते हैं, तो यह जोखिम होता है कि लोगों को सिर्फ यह बताने के लिए जगह मिल जाएगी कि आपका कोड आपके लिए क्या, कहां या क्यों दिया गया है। मैं इसे एक जगह के रूप में रखना चाहूँगा जो मैं सीखने आ सकता हूँ।
jramm

14
यह उत्तर साबित करता है कि प्रश्न की आपकी व्याख्या बहुत व्यापक है, बजाय इसके कि प्रश्न स्वयं भी व्यापक है।
jwg

17

यह ऑपरेटिंग सिस्टम पर निर्भर करता है कि फ़ाइल खोलने पर वास्तव में क्या होता है। नीचे मैं वर्णन करता हूं कि लिनक्स में क्या होता है क्योंकि यह आपको एक विचार देता है कि क्या होता है जब आप एक फ़ाइल खोलते हैं और आप स्रोत कोड की जांच कर सकते हैं यदि आप अधिक विवरण में रुचि रखते हैं। मैं अनुमतियों को कवर नहीं कर रहा हूं क्योंकि यह इस उत्तर को बहुत लंबा कर देगा।

लिनक्स में हर फाइल को इनकोड नामक संरचना से पहचाना जाता है। प्रत्येक संरचना में एक अद्वितीय संख्या होती है और प्रत्येक फ़ाइल को केवल एक इनोड संख्या मिलती है। यह संरचना एक फ़ाइल के लिए मेटा डेटा संग्रहीत करती है, उदाहरण के लिए फ़ाइल-आकार, फ़ाइल-अनुमतियाँ, समय टिकटों और पॉइंटर को डिस्क ब्लॉक, हालांकि, वास्तविक फ़ाइल नाम ही नहीं। प्रत्येक फ़ाइल (और निर्देशिका) में फ़ाइल नाम प्रविष्टि और लुकअप के लिए इनकोड नंबर होता है। जब आप एक फ़ाइल खोलते हैं, तो आपको लगता है कि आपके पास प्रासंगिक अनुमतियाँ हैं, फ़ाइल नाम के साथ जुड़े अद्वितीय इनोड संख्या का उपयोग करके एक फ़ाइल विवरणक बनाया जाता है। जैसा कि कई प्रक्रियाएं / एप्लिकेशन एक ही फ़ाइल को इंगित कर सकते हैं, इनोड में एक लिंक फ़ील्ड है जो फ़ाइल के लिंक की कुल गणना को बनाए रखता है। यदि कोई फ़ाइल किसी निर्देशिका में मौजूद है, तो इसकी लिंक गणना एक है, यदि इसकी कड़ी कड़ी है तो इसकी लिंक की संख्या दो होगी और यदि किसी प्रक्रिया द्वारा कोई फ़ाइल खोली जाती है, तो लिंक की संख्या 1 से बढ़ाई जाएगी।


6
वास्तविक प्रश्न से इसका क्या लेना-देना है?
बिल वुडगेर

1
यह बताता है कि लिनक्स में फाइल खोलने पर निम्न स्तर पर क्या होता है। मैं मानता हूं कि प्रश्न व्यापक है, इसलिए हो सकता है कि उत्तर उत्तर की तलाश में नहीं था।
एलेक्स

1
तो फिर, अनुमतियों के लिए कोई जाँच नहीं?
बिल वुडगेर

11

बहीखाता, ज्यादातर। इसमें "फ़ाइल मौजूद है?" जैसे विभिन्न चेक शामिल हैं। और "क्या मुझे लिखने के लिए इस फ़ाइल को खोलने की अनुमति है?"

लेकिन यह सब कर्नेल सामान है - जब तक आप अपने खुद के खिलौना ओएस को लागू नहीं कर रहे हैं, तब तक इसमें बहुत ज्यादा नहीं है (यदि आप हैं, तो मज़े करें - यह एक महान सीखने का अनुभव है)। बेशक, आपको अभी भी सभी संभावित त्रुटि कोड सीखना चाहिए जो आप एक फ़ाइल खोलते समय प्राप्त कर सकते हैं, ताकि आप उन्हें ठीक से संभाल सकें - लेकिन वे आम तौर पर बहुत कम सार होते हैं।

कोड स्तर पर सबसे महत्वपूर्ण हिस्सा यह है कि यह आपको खुली फ़ाइल का एक हैंडल देता है , जिसका उपयोग आप उन सभी अन्य कार्यों के लिए करते हैं जो आप फ़ाइल के साथ करते हैं। क्या आप इस मनमाने हैंडल के बजाय फ़ाइल नाम का उपयोग नहीं कर सकते थे? ठीक है, यकीन है - लेकिन एक हैंडल का उपयोग करने से आपको कुछ फायदे मिलते हैं:

  • सिस्टम उन सभी फ़ाइलों का ट्रैक रख सकता है जो वर्तमान में खुली हैं, और उन्हें हटाए जाने से रोकती हैं (उदाहरण के लिए)।
  • आधुनिक ओएस हैंडल के आसपास बनाए गए हैं - ऐसे कई उपयोगी चीजें हैं जो आप हैंडल से कर सकते हैं, और सभी विभिन्न प्रकार के हैंडल लगभग पहचान का व्यवहार करते हैं। उदाहरण के लिए, जब एक एसिंक्रोनस I / O ऑपरेशन विंडोज फ़ाइल हैंडल पर पूरा होता है, तो हैंडल को सिग्नल किया जाता है - यह आपको सिग्नल पर ब्लॉक करने की अनुमति देता है, जब तक कि यह सिग्नल नहीं हो जाता है, या ऑपरेशन को पूरी तरह से एसिंक्रोनस रूप से पूरा करने की अनुमति देता है। किसी फ़ाइल हैंडल पर प्रतीक्षा करना थ्रेड हैंडल पर प्रतीक्षा करने के समान ही है (जैसे कि थ्रेड समाप्त होने पर संकेत दिया जाता है), एक प्रोसेस हैंडल (फिर, प्रक्रिया समाप्त होने पर संकेत दिया जाता है), या सॉकेट (जब कुछ एसिंक्रोनस ऑपरेशन पूरा होता है)। बस महत्वपूर्ण रूप से, हैंडल उनके संबंधित प्रक्रियाओं के स्वामित्व में हैं, इसलिए जब एक प्रक्रिया अप्रत्याशित रूप से समाप्त हो जाती है (या एप्लिकेशन खराब तरीके से लिखा गया है), तो ओएस जानता है कि वह क्या हैंडल जारी कर सकता है।
  • अधिकांश परिचालनात्मक स्थितियाँ हैं - आप readअपनी फ़ाइल में अंतिम स्थिति से हैं। किसी फ़ाइल के किसी विशेष "ओपनिंग" की पहचान करने के लिए एक हैंडल का उपयोग करके, आप एक ही फ़ाइल में कई समवर्ती हैंडल रख सकते हैं, प्रत्येक अपने स्वयं के स्थानों से पढ़ सकते हैं। एक तरह से, हैंडल फ़ाइल में एक जंगम विंडो के रूप में कार्य करता है (और अतुल्यकालिक I / O अनुरोध जारी करने का एक तरीका है, जो बहुत काम आता है)।
  • हैंडल फ़ाइल नामों की तुलना में बहुत छोटे हैं । एक हैंडल आमतौर पर एक पॉइंटर का आकार होता है, आमतौर पर 4 या 8 बाइट्स। दूसरी ओर, फ़ाइल नाम में सैकड़ों बाइट्स हो सकते हैं।
  • हैंडल OS को फ़ाइल को स्थानांतरित करने की अनुमति देते हैं , भले ही अनुप्रयोगों में यह खुला हो - संभाल अभी भी मान्य है, और यह अभी भी उसी फ़ाइल को इंगित करता है, भले ही फ़ाइल का नाम बदल गया हो।

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


7

इसके मूल में जब कुछ भी नहीं पढ़ने के लिए खोलते हैं तो वास्तव में फैंसी होने की आवश्यकता होती है। यह सब करने की जरूरत है फ़ाइल मौजूद है की जाँच करें और आवेदन में इसे पढ़ने और एक हैंडल बनाने के लिए पर्याप्त विशेषाधिकार हैं जिस पर आप फ़ाइल पर रीड कमांड को जारी कर सकते हैं।

यह उन आदेशों पर है कि वास्तविक पढ़ने को भेजा जाएगा।

ओएस अक्सर संभाल से जुड़े बफर को भरने के लिए एक रीड ऑपरेशन शुरू करके पढ़ने पर एक हेड स्टार्ट प्राप्त करेगा। फिर जब आप वास्तव में पढ़ते हैं तो यह बफर की सामग्री को तुरंत वापस कर सकता है, बल्कि फिर डिस्क आईओ पर प्रतीक्षा करने की आवश्यकता होती है।

लिखने के लिए एक नई फ़ाइल खोलने के लिए ओएस को नई (वर्तमान में खाली) फ़ाइल के लिए निर्देशिका में एक प्रविष्टि जोड़ने की आवश्यकता होगी। और फिर से एक हैंडल बनाया जाता है, जिस पर आप राइट कमांड जारी कर सकते हैं।


5

मूल रूप से, कॉल को खोलने के लिए फ़ाइल खोजने की आवश्यकता होती है, और फिर जो कुछ भी करने की आवश्यकता होती है उसे रिकॉर्ड करें ताकि बाद में I / O संचालन इसे फिर से पा सकें। यह काफी अस्पष्ट है, लेकिन यह उन सभी ऑपरेटिंग सिस्टमों पर सच होगा जिन्हें मैं तुरंत सोच सकता हूं। बारीकियाँ एक मंच से दूसरे प्लेटफ़ॉर्म पर भिन्न होती हैं। यहाँ पर पहले से ही कई उत्तर आधुनिक समय के डेस्कटॉप ऑपरेटिंग सिस्टम की बात करते हैं। मैंने CP / M पर थोड़ी प्रोग्रामिंग की है, इसलिए मैं अपने ज्ञान की पेशकश करूँगा कि यह CP / M (MS-DOS पर कैसे काम करता है, शायद उसी तरह से काम करता है, लेकिन सुरक्षा कारणों से, यह आज भी आम तौर पर ऐसा नहीं किया जाता है )।

CP / M पर आपके पास FCB नामक एक चीज़ है (जैसा कि आपने C का उल्लेख किया है, आप इसे एक संरचना कह सकते हैं; यह वास्तव में RAM में 35-बाइट वाला एक अलग क्षेत्र है जिसमें विभिन्न क्षेत्र हैं)। FCB में डिस्क ड्राइव की पहचान करने के लिए फ़ाइल-नाम और (4-बिट) पूर्णांक लिखने के लिए फ़ील्ड हैं। फिर, जब आप कर्नेल की ओपन फाइल को कॉल करते हैं, तो आप एक सीपीयू के रजिस्टरों में इसे रखकर इस संरचना को एक पॉइंटर पास करते हैं। कुछ समय बाद, ऑपरेटिंग सिस्टम संरचना के साथ थोड़ा बदल जाता है। इस फ़ाइल में आप जो भी / ओ करते हैं, आप इस कॉल को सिस्टम कॉल के लिए एक पॉइंटर पास करते हैं।

CP / M इस FCB के साथ क्या करता है? यह अपने स्वयं के उपयोग के लिए कुछ क्षेत्रों को सुरक्षित रखता है, और इनका उपयोग फ़ाइल का ट्रैक रखने के लिए करता है, इसलिए आपने कभी भी उन्हें अपने कार्यक्रम के अंदर से नहीं छुएं। ओपन फाइल ऑपरेशन डिस्क के प्रारंभ में टेबल के माध्यम से एक फाइल के लिए उसी नाम से खोज करता है जैसे कि एफसीबी ('?' वाइल्डकार्ड वर्ण किसी भी वर्ण से मेल खाता है)। यदि यह एक फ़ाइल पाता है, तो यह डिस्क पर फ़ाइल के भौतिक स्थान (ओं) सहित FCB में कुछ जानकारी की प्रतिलिपि बनाता है, ताकि बाद में I / O कॉल अंततः BIOS को कॉल करें जो इन स्थानों को डिस्क चालक को पास कर सकता है। इस स्तर पर, बारीकियों में भिन्नता है।


-7

सरल शब्दों में, जब आप एक फाइल खोलते हैं, तो आप वास्तव में ऑपरेटिंग सिस्टम से अनुरोध कर रहे हैं कि वांछित फाइल को लोड करने के लिए (फाइल की सामग्री की प्रतिलिपि) प्रसंस्करण के लिए द्वितीयक भंडारण से रैम तक। और इसके पीछे का कारण (एक फ़ाइल लोड हो रहा है) है क्योंकि आप फ़ाइल को हार्ड-डिस्क से सीधे राम की तुलना में इसकी बेहद धीमी गति के कारण संसाधित नहीं कर सकते हैं।

ओपन कमांड एक सिस्टम कॉल उत्पन्न करेगा जो बदले में माध्यमिक भंडारण (हार्ड-डिस्क) से प्राथमिक भंडारण (राम) तक फ़ाइल की सामग्री की प्रतिलिपि बनाता है।

और हम एक फ़ाइल को 'बंद' करते हैं क्योंकि फ़ाइल की संशोधित सामग्री को मूल फ़ाइल पर प्रतिबिंबित करना पड़ता है जो हार्ड-डिस्क में है। :)

उम्मीद है की वो मदद करदे।

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