क्या होता है जब पेज कैश में 100% पेज वाली फाइल दूसरी प्रक्रिया द्वारा संशोधित हो जाती है


14

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

परिदृश्य: फ़ाइल / एप्लिकेशन / EXE, जो एक निष्पादन योग्य फ़ाइल है, पृष्ठ कैश में पूरी तरह से पृष्ठांकित है (इसके सभी पृष्ठ कैश / मेमोरी में हैं) और प्रक्रिया पी द्वारा निष्पादित किया जा रहा है।

निरंतर रिलीज तो एक नया निष्पादन योग्य के साथ बदल देता है / क्षुधा / EXE।

मान 1: मैं यह मानता हूं कि P (और किसी और को फ़ाइल डिस्क्रिप्टर के साथ पुराने निष्पादन योग्य का उल्लेख करते हुए) प्रक्रिया का उपयोग पुराने, मेमोरी / एप्स / EXE में बिना किसी समस्या के करना जारी रखेगा, और कोई भी नई प्रक्रिया जो उस पथ को निष्पादित करने की कोशिश करेगी नया निष्पादन योग्य।

अनुमान 2: मेरा मानना ​​है कि यदि फ़ाइल के सभी पृष्ठों को स्मृति में मैप नहीं किया जाता है, तो यह तब तक ठीक रहेगा जब तक कि फ़ाइल में पेज की आवश्यकता वाले पेज की गलती नहीं होती है, जिन्हें प्रतिस्थापित किया गया है, और शायद एक segfault होगा?

प्रश्न 1: यदि आप फ़ाइल के सभी पन्नों को mmtouch की तरह लगाते हैं, तो क्या इससे परिदृश्य बदल जाता है?

प्रश्न 2: यदि / apps / EXE एक दूरस्थ NFS पर है, तो क्या इससे कोई फर्क पड़ेगा? (मुझे नहीं लगता)

कृपया मेरी 2 मान्यताओं को सही या मान्य करें और मेरे 2 प्रश्नों का उत्तर दें।

मान लेते हैं कि यह एक CentOS 7.6 बॉक्स है, जिसमें कुछ 3.10.0-957.el7 कर्नेल है

अद्यतन: इसके बारे में आगे सोचते हुए, मुझे आश्चर्य है कि अगर यह परिदृश्य किसी भी अन्य गंदे पृष्ठ परिदृश्य से अलग नहीं है ..

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

मुझे संदेह है कि जब वर्तमान में निष्पादित कार्यक्रम समाप्त हो जाते हैं, तो कुछ भी नया बाइनरी का उपयोग करेगा। यह मानते हुए कि यह सब सही है, मुझे लगता है कि यह केवल दिलचस्प है जब फ़ाइल में से कुछ में ही पृष्ठांकित है।


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

जवाबों:


12

निरंतर रिलीज तो एक नया निष्पादन योग्य के साथ बदल देता है / क्षुधा / EXE।

यह महत्वपूर्ण हिस्सा है।

जिस तरह से एक नई फ़ाइल जारी की जाती है वह एक नई फ़ाइल (जैसे /apps/EXE.tmp.20190907080000) बनाकर होती है , सामग्री लिखती है, अनुमतियाँ और स्वामित्व सेट करती है और अंत में नाम बदलकर (2) इसे अंतिम नाम /apps/EXEमें बदल देती है, पुरानी फ़ाइल की जगह।

परिणाम यह है कि नई फ़ाइल में एक नया इनकोड नंबर है (जिसका अर्थ है, प्रभाव में, यह एक अलग फ़ाइल है।)

और पुरानी फ़ाइल का अपना इनोड नंबर था, जो वास्तव में अभी भी आसपास है, भले ही फ़ाइल का नाम अब इसे इंगित नहीं कर रहा है (या उस इनोड की ओर कोई फ़ाइल नाम इंगित नहीं कर रहे हैं।)

इसलिए, यहां कुंजी यह है कि जब हम लिनक्स में "फाइलों" के बारे में बात करते हैं, तो हम अक्सर "इनोड्स" के बारे में बात कर रहे होते हैं क्योंकि एक बार फाइल खोलने के बाद, इनोड वह संदर्भ होता है जिसे हम फाइल में रखते हैं।

मान 1 : मैं मानता हूं कि प्रक्रिया P (और पुराने डिसेबल को संदर्भित करने वाली फ़ाइल डिस्क्रिप्टर के साथ कोई भी) पुराने, मेमोरी / ऐप्स / EXE में बिना किसी समस्या के उपयोग करना जारी रखेगा, और कोई भी नई प्रक्रिया जो उस पथ को निष्पादित करने का प्रयास करती है नया निष्पादन योग्य।

सही बात।

अनुमान 2 : मेरा मानना ​​है कि यदि फ़ाइल के सभी पृष्ठों को स्मृति में मैप नहीं किया जाता है, तो यह तब तक ठीक रहेगा जब तक कि फ़ाइल में पेज की आवश्यकता वाले पेज की गलती नहीं होती है, जिन्हें प्रतिस्थापित किया गया है, और शायद एक segfault होगा?

गलत। पुराना इनकोड अभी भी आसपास है, इसलिए पुराने बाइनरी का उपयोग करने वाली प्रक्रिया से पेज दोष अभी भी डिस्क पर उन पृष्ठों को खोजने में सक्षम होंगे।

आप पुराने बाइनरी को चलाने वाली प्रक्रिया के लिए /proc/${pid}/exeसिमलिंक (या, समकक्ष, lsofआउटपुट) को देखकर इसके कुछ प्रभाव देख सकते हैं , जो यह /app/EXE (deleted)संकेत देने के लिए दिखाएगा कि नाम अब नहीं है, लेकिन इनोड अभी भी आसपास है।

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

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

प्रश्न 1 : यदि आप फ़ाइल के सभी पृष्ठों को vmtouch के साथ कुछ इस तरह बदलते हैं कि परिदृश्य बदल जाता है

यह प्रश्न गलत धारणा 2 पर आधारित है कि पृष्ठों को लॉक नहीं करने से सीफ़ॉल्ट पैदा होंगे। यह नहीं होगा

प्रश्न 2 : यदि / apps / EXE एक दूरस्थ NFS पर है, तो क्या इससे कोई फर्क पड़ेगा? (मुझे नहीं लगता)

यह है मतलब एक ही तरह से समय यह होता है की सबसे अधिक काम करते हैं और करने के लिए, लेकिन कुछ "gotchas" एनएफएस के साथ देखते हैं।

कभी-कभी आप एक फ़ाइल को हटाने की कलाकृतियों को देख सकते हैं जो अभी भी NFS में खुली हुई है (उस निर्देशिका में छिपी हुई फ़ाइल के रूप में दिखाई देती है।)

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

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


1
क्या नाम बदलने (2) को तब तक ब्लॉक किया जाता है जब तक कि पुरानीनाम फ़ाइल की रेफरी संख्या शून्य नहीं हो जाती?
ग्रीग लेवेंटल

2
नहीं, नाम (2) ब्लॉक नहीं होगा। पुराने इनोड को संभावित रूप से बहुत लंबे समय के लिए चारों ओर रखा जाता है।
फाइलब्रांडेन

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

4
@GreggLeventhal: "मैं आपके द्वारा उपयोग की जा रही निरंतर रिलीज़ प्रक्रिया के बारे में क्या धारणा बना रहा हूँ जिससे आपको निश्चित रूप से अस्थायी फ़ाइलों का उपयोग करना पड़ता है?" - क्योंकि जब तक यूनिक्स मौजूद है, ऐसा करने का एकमात्र एकमात्र तरीका है। renameकाफी केवल फ़ाइल और फाइल सिस्टम आपरेशन है कि परमाणु होने की गारंटी है (हम नहीं पार फाइल सिस्टम या उपकरण सीमाओं को करना यह सोचते हैं), तो "अस्थायी फ़ाइल बनाने और उसके बाद है rename" है फ़ाइलों को अपडेट करने के लिए मानक पैटर्न। यह भी उदाहरण के लिए यूनिक्स पर हर पाठ संपादक का उपयोग करता है।
जॉर्ग डब्ल्यू मित्तग

1
@ grahamj42: renameपोसिक्स का हिस्सा है। दी गई, यह आईएसओ सी (वर्तमान ड्राफ्ट में धारा 7.21.4.2) के संदर्भ में शामिल है, लेकिन यह वहां है।
जार्ज डब्ल्यू मित्तग

7

अनुमान 2: मेरा मानना ​​है कि यदि फ़ाइल के सभी पृष्ठों को स्मृति में मैप नहीं किया जाता है, तो यह तब तक ठीक रहेगा जब तक कि फ़ाइल में पेज की आवश्यकता वाले पेज की गलती नहीं होती है, जिन्हें प्रतिस्थापित किया गया है, और शायद एक segfault होगा?

नहीं, ऐसा नहीं होगा, क्योंकि कर्नेल आपको फ़ाइल के अंदर कुछ भी बदलने के लिए खोलने की अनुमति नहीं देगा, जिसे वर्तमान में निष्पादित किया गया है। इस तरह की कार्रवाई विफल रहेगी ETXTBSY[1]:

cp /bin/sleep sleep; ./sleep 3600 & echo none > ./sleep
[9] 5332
bash: ./sleep: Text file busy

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

[१] इस तरह की सुरक्षा को अन्य फाइलों तक नहीं बढ़ाया जाता है, जिसे "पाठ" (लाइव कोड / निष्पादन योग्य) भी माना जा सकता है: साझा पुस्तकालय, जावा कक्षाएं, आदि; इस तरह के एक फ़ाइल को संशोधित करने के अन्य प्रक्रिया द्वारा मैप किए गए, जबकि होगा यह क्रैश हो। लिनक्स पर, डायनेमिक लिंकर को कर्तव्यपूर्वक MAP_DENYWRITEध्वज को पास करता है mmap(2), लेकिन कोई गलती नहीं करता है - इसका कोई प्रभाव नहीं पड़ता है।


1
Dpkg परिदृश्य में, किस बिंदु पर फिर से नाम पूरा होता है जैसे कि / apps / EXE के लिए डेंट्री नए बाइनरी के इनकोड को संदर्भित करेगा? जब पुराने का कोई संदर्भ नहीं है? वह कैसे काम करता है?
ग्रीग लेवेंथल

2
rename(2)परमाणु है; जैसे ही यह पूरा हो गया है, dir प्रविष्टि नई फ़ाइल को संदर्भित करती है। जो प्रक्रियाएं उस बिंदु पर अभी भी पुरानी फ़ाइल का उपयोग कर रही थीं, वे केवल इसे मौजूदा मैपिंग के माध्यम से, या इसके लिए खुले हैंडल के माध्यम से एक्सेस करने में सक्षम होंगी (जो कि एक अनाथ दंत चिकित्सा का संदर्भ ले सकती है, जो अब इसके अलावा अन्य सुलभ नहीं है /proc/PID/fd)।
मस्जिद

1
मुझे आपका उत्तर सबसे अच्छा लगता है क्योंकि आपके ETXTBSY उल्लेख ने मुझे इस utcc.utoronto.ca/~cks/space/blog/unix/WhyTextFileBusyError का नेतृत्व किया जो मेरे सभी सवालों का जवाब देता है।
ग्रेग लेवेंथल

4

फाइलब्रांडेन का जवाब सही है कि निरंतर रिलीज की प्रक्रिया फाइलों के माध्यम से उचित परमाणु प्रतिस्थापन करती है rename। यदि यह नहीं है, लेकिन फ़ाइल को इन-प्लेस संशोधित करता है, तो चीजें अलग होती हैं। हालाँकि आपका मानसिक मॉडल अभी भी गलत है।

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

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

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