क्या रैम में भरी जाने वाली प्रक्रियाओं द्वारा फाइलें खोली जाती हैं?


24

उदाहरण के लिए sed, कमांड्स प्रोग्राम हैं और प्रोग्राम एक फाइल के अंदर कोडित लॉजिक होते हैं और ये फाइल हार्ड डिस्क पर कहीं होती हैं। हालाँकि जब कमांड चलाए जा रहे होते हैं, हार्ड डिस्क से उनकी फ़ाइलों की एक कॉपी रैम में डाल दी जाती है , जहाँ वे जीवन में आते हैं और सामान कर सकते हैं और प्रक्रियाएं कहलाती हैं

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

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

मेरी धारणा है, कि प्रक्रियाओं द्वारा खोली गई फ़ाइलें भी RAM में लोड की जाती हैं। मुझे नहीं पता कि क्या यह सच है, यह सिर्फ एक अंतर्ज्ञान है।

कृपया, कोई इसे समझ सकता है?


जवाबों:


27

हालाँकि जब कमांड चलाए जा रहे हैं, हार्ड डिस्क से उनकी फ़ाइलों की एक कॉपी रैम में डाल दी जाती है,

यह गलत है (सामान्य रूप में)। जब कोई प्रोग्राम निष्पादित होता है (थ्रू एग्जीक्यूट (2) ...) प्रोसेस (उस प्रोग्राम को चलाने वाला) अपना वर्चुअल एड्रेस स्पेस बदल रहा है और कर्नेल उस उद्देश्य के लिए MMU को फिर से कॉन्फ़िगर कर रहा है। वर्चुअल मेमोरी के बारे में भी पढ़ें । सूचना है कि आवेदन कार्यक्रमों का उपयोग कर अपने वर्चुअल ऐड्रेस स्पेस बदल सकते हैं mmap (2) और munmapऔर mprotect (2) , भी द्वारा इस्तेमाल किया गतिशील लिंकर (देखें ld-linux (8) )। यह भी देखें madvise (2) और posix_fadvise (2) और mlock (2)

भावी पृष्ठ दोषों को निष्पादन योग्य फ़ाइल से लोड (lazily) पृष्ठों के लिए कर्नेल द्वारा संसाधित किया जाएगा। थ्रैशिंग के बारे में भी पढ़ें ।

कर्नेल बड़े पृष्ठ कैश को बनाए रखता है । कॉपी-ऑन-राइट के बारे में भी पढ़ें । रेडहेड (2) भी देखें ।

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

के लिए सिस्टम कॉल की तरह पढ़ने के लिए (2) और लिखने (2) पेज कैश भी प्रयोग किया जाता है। यदि पढ़ा जाने वाला डेटा इसमें बैठा है, तो कोई डिस्क IO नहीं किया जाएगा। यदि डिस्क IO की आवश्यकता होती है, तो पढ़ा गया डेटा पेज कैश में डाल दिया जाएगा। तो, व्यवहार में, यदि आप एक ही कमांड को दो बार चलाते हैं, तो ऐसा हो सकता है कि डिस्क पर कोई भौतिक I / O दूसरी बार नहीं किया जाता है (यदि आपके पास एक पुरानी घूर्णन हार्ड डिस्क है - एसएसडी नहीं - आप सुन सकते हैं; या अपनी हार्ड डिस्क एलईडी का ध्यानपूर्वक निरीक्षण करें)।

मैं ऑपरेटिंग सिस्टम जैसी एक पुस्तक पढ़ने की सलाह देता हूं : तीन आसान टुकड़े (स्वतंत्र रूप से डाउनलोड करने योग्य, प्रति अध्याय एक पीडीएफ फाइल) जो यह सब बताते हैं।

यह भी देखें लिनक्स खाया मेरे राम की तरह और चलाने के आदेशों xosview, top, htopया cat /proc/self/mapsया cat /proc/$$/maps(देखें proc (5) )।

पुनश्च। मैं लिनक्स पर ध्यान केंद्रित कर रहा हूं, लेकिन अन्य ओएस में वर्चुअल मेमोरी और पेज कैश भी है।


35

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

इसके साथ भी awkऐसा ही है। यह एक समय में एक रिकॉर्ड पढ़ता है , जो डिफ़ॉल्ट रूप से एक पंक्ति है। यदि आप इनपुट डेटा के कुछ हिस्सों को चर में स्टोर करते हैं, तो यह अतिरिक्त होगा, निश्चित रूप से 1

कुछ लोगों को जैसे काम करने की आदत होती है

for line in $(cat file); do ...; done

चूंकि शेल को लूप $(cat file)के पहले पुनरावृत्ति को चलाने से पहले कमांड प्रतिस्थापन का पूरी तरह से विस्तार करना होगाfor , यह पूरी मेमोरी में पढ़ेगा ( लूप निष्पादित करने वाले शेल द्वारा उपयोग की जाने वाली मेमोरी में )। यह थोड़ा मूर्खतापूर्ण है और अयोग्य भी है। इसके बजाय, एक करना चाहिएfilefor

while IFS= read -r line; do ...; done <file

यह fileलाइन को लाइन से प्रोसेस करेगा (लेकिन "IFS = read -r line" को समझें )।

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

मैं जैव सूचना विज्ञान में काम कर रहा हूं, और जब मैं भारी मात्रा में जीनोमिक डेटा का प्रसंस्करण कर रहा हूं, तब तक मैं बहुत कुछ नहीं कर पाऊंगा, जब तक कि मैं केवल डेटा के बिट्स को याद में रखूं। उदाहरण के लिए, जब मुझे वीसीएफ फ़ाइल में डीएनए वेरिएंट वाले 1 टेराबाइट डेटासेट से व्यक्तियों की पहचान करने के लिए उपयोग किए जा सकने वाले डेटा के बिट्स को उतारने की आवश्यकता होती है (क्योंकि उस प्रकार के डेटा को सार्वजनिक नहीं किया जा सकता है), मैं लाइन से लाइन करता हूं एक साधारण awkकार्यक्रम के साथ प्रसंस्करण (यह संभव है क्योंकि वीसीएफ प्रारूप लाइन-ओरिएंटेड है)। मैं फ़ाइल को मेमोरी में नहीं पढ़ता, इसे वहां प्रोसेस करता हूं , और इसे फिर से लिखता हूं ! यदि फ़ाइल संपीड़ित होती है, तो मैं इसे zcatया उसके माध्यम से खिलाऊंगा gzip -d -c, जो gzipकि डेटा की स्ट्रीम प्रोसेसिंग करता है, पूरी फ़ाइल को मेमोरी में भी नहीं पढ़ेगा।

यहां तक ​​कि फ़ाइल स्वरूपों के साथ जो लाइन ओरिएंटेड नहीं हैं , जैसे कि JSON या XML, स्ट्रीम पार्सर हैं जो रैम में सभी को संग्रहीत किए बिना बड़ी फ़ाइलों को संसाधित करना संभव बनाता है।

निष्पादनयोग्य के साथ, यह थोड़ा अधिक जटिल है क्योंकि साझा पुस्तकालयों को मांग पर लोड किया जा सकता है, और / या प्रक्रियाओं के बीच साझा किया जा सकता है ( उदाहरण के लिए साझा पुस्तकालयों और रैम उपयोग का लोड देखें )।

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


1 तकनीकी रूप से, अधिकांश प्रोग्राम संभवतया एक समय में इनपुट डेटा का एक हिस्सा पढ़ते हैं, या तो स्पष्ट बफ़रिंग का उपयोग करते हैं, या स्पष्ट रूप से बफरिंग के माध्यम से मानक I / O लाइब्रेरी करते हैं, और फिर उस चंक लाइन को उपयोगकर्ता के कोड से लाइन में प्रस्तुत करते हैं। एक समय में एक चरित्र की तुलना में डिस्क के ब्लॉक आकार के कई को पढ़ना अधिक कुशल है। हालांकि इस चंक का आकार शायद ही मुट्ठी भर किलोबाइट से बड़ा होगा।


आपने कहा, साझा पुस्तकालयों को रैम में लोड करना संभव है, क्या एक नियमित फ़ाइल को लोड करना भी संभव है, जिसमें रैम में केवल डेटा होता है, भले ही इसका कोई मतलब न हो?
शार्क

1
@ शेखर का कोर्स। यह केवल एक चर (या सरणी, या हैश, या जो भी डेटा संरचना को प्रश्न आपूर्ति में भाषा) में जोड़ने की बात है, जब तक कि सभी फ़ाइल संग्रहीत नहीं की जाती है। के साथ awk, { a[i++] = $0 }सरणी में इनपुट फ़ाइल की सभी पंक्तियों को जोड़ देगा a। आप सी फ़ंक्शन को भी देखना चाहते हैं mmap(), लेकिन इसका उपयोग यहां थोड़ा बंद विषय हो सकता है।
Kusalananda

6
sed, awkऔर अन्य लाइन-ओरिएंटेड प्रोग्राम मेमोरी में एक समय में एक लाइन नहीं पढ़ते हैं, क्योंकि प्लेन टेक्स्ट फाइल्स में लाइन इंडेक्स नहीं होता है, और फाइलसिस्टम एपीआई और लो-लेवल स्टोरेज हार्डवेयर एक या अधिक "सेक्टर" (आमतौर पर 512) पढ़ता है या एक बार में 1024 बाइट्स)। मुझे आश्चर्य होगा कि 8KB से कम पहले लाइन द्वारा संसाधित होने से पहले ओएस द्वारा मेमोरी में पढ़ा गया था।
रसेल बोरोगोव

5
यद्यपि एक उपयोगिता sedएक मेमोरी में एक समय में केवल एक पंक्ति पढ़ेगी, लेकिन यह ध्यान देने योग्य है कि ऑपरेटिंग सिस्टम फ़ाइलों को कैश करने के लिए मुफ्त रैम का उपयोग करेगा ताकि उन्हें जल्दी से एक्सेस किया जा सके। यदि आप sedएक छोटी फ़ाइल पर चल रहे हैं, तो यह संभव है कि OS पूरी फ़ाइल को मेमोरी में कैश कर देगा और ऑपरेशन पूरी तरह से रैम में किया जाएगा। देखें: en.wikipedia.org/wiki/Page_cache
सीन डॉसन

5
@ अक्षरक फ़ाइल का उपयोग पूरी तरह से मेमोरी में सुलभ है (अन्य उत्तर देखें, mmap यहाँ कीवर्ड सिस्टम कॉल है)। उदाहरण के लिए, एक डेटाबेस सिस्टम आमतौर पर आसानी से और एक्सेस की गति, पूरे डेटाबेस या कम से कम कुछ सूचकांकों को स्मृति में मैप करना चाहता है। यह जरूरी नहीं है कि पूरी बात वास्तव में स्मृति में है। ओएस "बहाना" करने के लिए स्वतंत्र है कि फ़ाइल मेमोरी में है। यह एप्लिकेशन को "यहां, मेमोरी की इस श्रेणी में आपकी फ़ाइल है" बताता है, और केवल एक बार पढ़ने के बाद (जैसे कि जब प्रक्रिया को स्वैप किया गया है), डेटा वास्तव में पढ़ा जाता है।
जोनास श्फर

5

नहीं। इन दिनों रैम के शानदार होने के बावजूद, एक समय था जब रैम बहुत सीमित संसाधन था (मैंने 2MB रैम के साथ एक VAX 11/750 पर प्रोग्रामिंग सीखी थी) और रैम में एकमात्र चीज सक्रिय निष्पादन योग्य और डेटा पृष्ठ थी सक्रिय प्रक्रियाओं और फ़ाइल डेटा जो बफ़र कैश में था।
बफ़र कैश को फ़्लश किया गया था, और डेटा पेज स्वैप किए गए थे। और बार-बार। केवल पढ़ने योग्य निष्पादन योग्य पृष्ठ ही लिखित और पृष्ठ तालिकाओं से अधिक थे, इसलिए यदि प्रोग्राम उन पृष्ठों को फिर से छूता है, जो वे फाइलसिस्टम से पृष्ठांकित थे। डेटा को स्वैप से पृष्ठांकित किया गया था। जैसा कि ऊपर उल्लेख किया गया है, STDIO पुस्तकालय ब्लॉकों में डेटा में खींच लिया गया था और आवश्यकतानुसार कार्यक्रम द्वारा प्राप्त किया गया था: fgetc, fgets, fread, आदि। mmap के साथ, एक फ़ाइल को प्रक्रिया के पते स्थान में मैप किया जा सकता है, जैसे कि इसके साथ किया जाता है। साझा लाइब्रेरी ऑब्जेक्ट या यहां तक ​​कि नियमित फ़ाइलें। हाँ, आपके पास कुछ हद तक नियंत्रण हो सकता है यदि इसकी रैम (mlock) में नहीं है, लेकिन यह केवल इतना आगे जाता है (mlock का त्रुटि कोड अनुभाग देखें)।


1
"आपकी रैम आपकी फ़ाइलों के लिए बहुत छोटी होने जा रही है" कथन अब सच है क्योंकि यह वैक्स के पुराने दिनों में था।
फेडरिको पोलोनी

1
@Federico_Poloni आज बिलकुल भी सच नहीं है। मेरे आखिरी नियोक्ता में हमारे पास 1Tb रैम और सिर्फ 0.5Tb हार्ड डिस्क वाला वर्कस्टेशन क्लास पीसी था। (समस्या वर्ग: छोटे इनपुट, मध्यम आउटपुट, गणना के दौरान बड़े बेतरतीब ढंग से एक्सेस किए गए सरणियाँ)।
nigel222
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.