यूनिक्स प्रणालियों पर, हमें स्पष्ट रूप से `खुला ()` और `पास ()` फ़ाइलों को `पढ़ने ()` या `लिखने ()` उन्हें करने में सक्षम होने के लिए क्यों है?


50

यूनिक्स फाइल सिस्टम डिज़ाइन में क्यों open()और क्या close()मौजूद है?

क्या OS केवल पहली बार पता नहीं लगा सका read()या write()बुलाया गया था और जो कुछ open()भी सामान्य रूप से करेगा?


22
यह ध्यान देने योग्य है कि यह मॉडल फाइलसिस्टम का हिस्सा नहीं है , बल्कि यूनिक्स एपीआई का है । फाइलसिस्टम केवल इस बात से संबंधित है कि डिस्क कहां पर है और ब्यूटेन कहां रखा जाए, आदि। यूनिक्स या एक्सएल 4 जैसे यूनिक्स फाइलसिस्टम के शीर्ष पर आपके द्वारा वर्णित वैकल्पिक मॉडल का होना पूरी तरह से संभव होगा। कर्नेल को फाइल सिस्टम के लिए उचित अपडेट में अनुवाद करने के लिए (जैसा अभी है)।
15

18
के रूप में, मुझे लगता है कि यह क्यों open()मौजूद है के बारे में अधिक है। "क्या OS पहली बार पढ़े () या लिखने () का पता लगाने और जो कुछ भी खुले () करेगा वह सामान्य रूप से नहीं होगा?" क्या समापन के लिए कोई संगत सुझाव होगा?
जोशुआ टेलर

7
आप कैसे बताएंगे read()या write()किस फ़ाइल को एक्सेस करना है? संभवतः मार्ग से गुजरते हुए। यदि आप इसे एक्सेस कर रहे हैं (दो read()या write()कॉल के बीच ) फ़ाइल का पथ बदल जाता है तो क्या होगा ?
user253751

2
इसके अलावा, आप आमतौर पर read()और write()बस पर नियंत्रण का उपयोग नहीं करते हैं open()
पावेल Paमरदा 20

6
@ जॉनी: आप शायद भूल रहे हैं कि उन दिनों हार्डवेयर कितना सीमित था। पीडीपी -7 जिस पर यूनिक्स को पहली बार लागू किया गया था (प्रति गूगल) अधिकतम 64K RAM और 0.333 MHz घड़ी थी - बल्कि इन दिनों एक साधारण माइक्रोकंट्रोलर से कम थी। इस तरह का कचरा संग्रह करना, या फ़ाइल एक्सेस की निगरानी के लिए सिस्टम कोड का उपयोग करना, सिस्टम को अपने घुटनों पर ले आया होगा।
jamesqf

जवाबों:


60

डेनिस रिची में «यूनिक्स टाइम-शेयरिंग सिस्टम के विकास» का उल्लेख है openऔर closeइसके साथ ही read, writeऔर creatशुरू से ही सिस्टम में मौजूद थे।

मैं बिना एक प्रणाली लगता है openऔर closeसमझ से बाहर नहीं होगा, फिर भी मेरा मानना है कि यह डिजाइन को मुश्किल होगा। आप आम तौर पर केवल एक ही नहीं बल्कि कई पढ़ना और लिखना चाहते हैं, और यह शायद उन पुराने कंप्यूटरों पर बहुत सीमित रैम के साथ सच था जो UNIX पर उत्पन्न हुए थे। एक हैंडल होना जो आपकी वर्तमान फ़ाइल स्थिति को बनाए रखता है, इसे सरल बनाता है। अगर readयाwriteहैंडल को वापस करने के लिए थे, उन्हें एक जोड़ी लौटना होगा - एक हैंडल और अपनी स्वयं की वापसी स्थिति। जोड़ी का संभाल हिस्सा अन्य सभी कॉलों के लिए बेकार होगा, जो उस व्यवस्था को अजीब बना देगा। कर्सर की स्थिति को कर्नेल तक छोड़ने से यह न केवल बफरिंग द्वारा दक्षता में सुधार करने की अनुमति देता है। पथ लुकअप से जुड़ी कुछ लागतें भी हैं - एक हैंडल होने से आप इसे केवल एक बार भुगतान कर सकते हैं। इसके अलावा, UNIX विश्वदृष्टि की कुछ फ़ाइलों में एक फ़ाइल सिस्टम पथ भी नहीं है (या नहीं - अब वे जैसी चीजें करते हैं /proc/self/fd)।


7
पथ देखने और अनुमति जाँच आदि की लागत बहुत महत्वपूर्ण है। यदि आप बिना open/ के एक सिस्टम बनाना चाहते हैं close, तो आप /dev/stdoutपाइपिंग की अनुमति देने के लिए सामान को लागू करना सुनिश्चित करेंगे ।
पीटर कॉर्ड्स

5
मुझे लगता है कि इसका एक और पहलू यह है कि जब आप फ़ाइल को खोलकर रखते हैं तो कई रीड्स का उपयोग करते हुए आप उस फाइल को उसी फाइल में रख सकते हैं। अन्यथा, आपके पास ऐसे मामले हो सकते हैं जहां एक और प्रक्रिया उसी नाम से एक फ़ाइल को फिर से बनाती है और फिर से बनाती है, और एक फाइल को चंक में पढ़ना प्रभावी रूप से पूरी तरह से असंगत हो सकता है। (इसमें से कुछ फाइलसिस्टम पर भी निर्भर हो सकता है।)
ब्रूनो

2
मैंने बिना पास के एक डिजाइन किया (); आप पढ़ने और () और लिखने () को इनोड संख्या और ऑफ़सेट पास करते हैं। मैं बिना खुले () के बहुत आसानी से नहीं कर सकता क्योंकि नाम संकल्प रहता है।
यहोशू

3
@ जोशुआ: इस तरह की प्रणाली में मौलिक रूप से अलग शब्दार्थ होते हैं क्योंकि यूनिक्स फाइल डिस्क्रिप्टर फाइलों (इनोड्स) का उल्लेख नहीं करते हैं, लेकिन फाइल विवरण खोलने के लिए , जिनमें से किसी दिए गए फ़ाइल (इनोड) के लिए कई हो सकते हैं।
आर ..

@Joshua, तो आप सिर्फ नाम बदला open()करने के लिए get_inode()और पूरी व्यवस्था और अधिक कठोर (असंभव पढ़ने / एक साथ कई स्थानों पर एक ही फाइल लिखने के लिए) बनाया है।
वॉनब्रांड

53

फिर सभी readऔर writeकॉल को प्रत्येक ऑपरेशन पर यह जानकारी देनी होगी:

  • फ़ाइल का नाम
  • फ़ाइल की अनुमति
  • चाहे कॉल करने वाला एप बना रहा हो या बना रहा हो
  • क्या कॉल करने वाले को फ़ाइल के साथ काम किया जाता है (अप्रयुक्त रीड-बफ़र्स को त्यागने और लिखने-बफ़र्स को वास्तव में लिखना सुनिश्चित करने के लिए)

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


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

5
"फ़ाइल" में पहले स्थान पर नाम या अनुमति नहीं हो सकती है; readऔर writeउन फाइलों तक ही सीमित नहीं हैं जो एक फाइल सिस्टम पर रहते हैं, और यह यूनिक्स में एक मौलिक डिजाइन निर्णय है, जैसा कि pjc50 बताते हैं।
रिस्टोरियरपोस्ट

1
यह भी पढ़ें कि इसे लिखने / लिखने की फाइल कहाँ है - शुरुआत, अंत, या एक मनमाना स्थिति (आमतौर पर अंतिम पढ़ने / लिखने के अंत के तुरंत बाद) - कर्नेल आपके लिए इस पर नज़र रखता है (एक मोड के साथ) प्रत्यक्ष सभी फ़ाइल के अंत तक लिखते हैं, या अन्यथा फाइलें शुरुआत में स्थिति के साथ खोली जाती हैं और प्रत्येक पढ़ने / लिखने के साथ उन्नत होती हैं और साथ ले जाया जा सकता है lseek)
Random832

51

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

यदि आप कई साधारण मानक UNIX उपयोगिताओं को देखते हैं grep, जैसे कि विशेष रूप से उनके मूल संस्करणों में, आप देखेंगे कि वे कॉल को शामिल नहीं करते हैं open()और close()फिर readऔर write। फ़ाइल हैंडल को शेल द्वारा प्रोग्राम के बाहर स्थापित किया जाता है और इसे शुरू करने पर पास किया जाता है। इसलिए प्रोग्राम को परवाह नहीं है कि वह किसी फाइल पर लिख रहा है या किसी अन्य प्रोग्राम में।

साथ ही open, फ़ाइल वर्णनकर्ता होने का अन्य तरीके हैं socket, listen, pipe, dup, और पाइप से अधिक फ़ाइल वर्णनकर्ता भेजने के लिए एक बहुत हीथ रॉबिन्सन तंत्र: https://stackoverflow.com/questions/28003921/sending-file-descriptor-by-linux -socket

संपादित करें: कुछ व्याख्यान नोट जो अप्रत्यक्ष की परतों का वर्णन करते हैं और यह कैसे O_APPEND को समझदारी से काम करते हैं। ध्यान दें कि इनोड डेटा को मेमोरी में रखने की गारंटी देता है कि सिस्टम को अगले लिखने के ऑपरेशन के लिए उन्हें फिर से लाने और लाने की जरूरत नहीं होगी।


1
इसके अलावा creat, और listenएक fd नहीं बनाता है, लेकिन जब (और यदि) एक अनुरोध आता है, तो सुनता acceptहै और नए (जुड़े) सॉकेट के लिए एक fd देता है।
dave_thompson_085

18
यह सही जवाब है। फ़ाइल डिस्क्रिप्टर पर संचालन का प्रसिद्ध (छोटा) सेट सभी प्रकार के संसाधनों के लिए एक एकीकृत एपीआई है जो डेटा का उत्पादन या उपभोग करता है। यह अवधारणा HUGELY सफल है। एक स्ट्रिंग में वास्तविक स्थान (URL किसी भी?) के साथ संसाधन प्रकार को परिभाषित करने वाला एक वाक्यविन्यास हो सकता है, लेकिन उन स्ट्रिंग को कॉपी करने के लिए जो उपलब्ध रैम के कई प्रतिशत पर कब्जा कर लेते हैं (पीडीपी 7? 16 kB पर क्या अत्यधिक है)? ।
पीटर - मोनिका

शायद यह होगा, यदि निम्न-स्तरीय कॉल और शेल एक ही समय में विकसित किए गए थे। लेकिन pipeयूनिक्स पर विकास शुरू होने के कुछ साल बाद पेश किया गया था।
थॉमस डिकी

1
@ थोमस डिके: जो केवल दिखाता है कि मूल डिजाइन कितना अच्छा था, क्योंकि इसने पाइप और सी को सरल विस्तार की अनुमति दी थी :-)
jamesqf

लेकिन तर्क की उस पंक्ति के बाद, यह उत्तर कुछ भी नया नहीं प्रदान करता है।
थॉमस डिक्की

10

उत्तर नहीं है, क्योंकि खुले () और पास () क्रमशः एक हैंडल बनाते हैं और नष्ट करते हैं। ऐसे समय हैं (ठीक है, हर समय, वास्तव में) जहां आप यह गारंटी देना चाहते हैं कि आप किसी विशेष एक्सेस स्तर वाले एकमात्र कॉलर हैं, क्योंकि किसी अन्य कॉलर (उदाहरण के लिए) को किसी फ़ाइल पर लिखना जो आप अप्रत्याशित रूप से छोड़ रहे हैं। एक अज्ञात राज्य में एक आवेदन या एक livelock या गतिरोध का नेतृत्व, जैसे डाइनिंग फिलोसोफर्स लेम्मा।

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


7

ओपन () का उपयोग करते समय फ़ाइलों को लॉक करने का एक तरीका प्रदान करता है। यदि फ़ाइलें स्वचालित रूप से खोली गईं, पढ़ी / लिखी गईं और फिर OS द्वारा बंद कर दी गईं, तो उन फ़ाइलों को संचालन के बीच बदलने वाले अन्य अनुप्रयोगों को रोकने के लिए कुछ भी नहीं होगा।

हालांकि यह प्रबंधनीय हो सकता है (कई सिस्टम सादगी के लिए गैर-अनन्य फ़ाइल एक्सेस का समर्थन करते हैं) अधिकांश एप्लिकेशन यह मानते हैं कि उनके पास खुली हुई फाइलें नहीं बदलती हैं।


5

क्योंकि आप मान रहे हैं कि फ़ाइल का पथ आगे बढ़ सकता है।


4

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

यदि ओएस खुला / बंद नहीं था, तो readया के साथ write, उन फ़ाइल कार्रवाइयों को अभी भी हर बार किसी भी आरंभीकरण, बफर फ्लशिंग / प्रबंधन, आदि का प्रदर्शन करना होगा। यह दोहरावदार पढ़ने और लिखने के लिए थोपने के लिए बहुत कुछ है।


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

1

यूनिक्स मंत्र "चीजों को करने का एक तरीका प्रदान करता है", जिसका अर्थ है "फैक्टरिंग" को वसीयत में संयोजित करने के लिए (पुन: प्रयोज्य) टुकड़ों में। यानी, इस मामले में फ़ाइल के निर्माण और विनाश को उनके उपयोग से अलग किया जाता है। महत्वपूर्ण लाभ बाद में आए, पाइप और नेटवर्क कनेक्शन के साथ (उन्हें फ़ाइल हैंडल के माध्यम से भी हेरफेर किया जाता है, लेकिन वे अन्य तरीकों से बनाए जाते हैं)। चारों ओर फ़ाइल हैंडल करने में सक्षम होने के नाते (उदाहरण के लिए उन्हें "खुली फ़ाइलों" के रूप में बच्चे की प्रक्रियाओं को पास करना जो जीवित रहते हैं exec(2), और यहां तक ​​कि एक पाइप के माध्यम से असंबंधित प्रक्रियाएं) केवल इस तरह से संभव हैं। विशेष रूप से यदि आप एक संरक्षित फ़ाइल के लिए नियंत्रित पहुँच प्रदान करना चाहते हैं। इसलिए आप उदाहरण के लिए खोल सकते हैं/etc/passwd लिखने के लिए, और पास करें कि एक बच्चे की प्रक्रिया को लिखने के लिए उस फ़ाइल को खोलने की अनुमति नहीं है (हाँ, मुझे पता है कि यह एक हास्यास्पद उदाहरण है, कुछ और यथार्थवादी के साथ संपादित करने के लिए स्वतंत्र महसूस करें)।

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