यूनिक्स / लिनक्स में पाइप कमांड को समझना


16

मेरे पास दो सरल कार्यक्रम हैं: Aऔर B। Aपहले चलता था, फिर B"स्टडआउट" प्राप्त Aकरता है और इसे अपने "स्टडिन" के रूप में उपयोग करता है। मान लें कि मैं एक GNU / Linux ऑपरेटिंग सिस्टम का उपयोग कर रहा हूं और ऐसा करने का सबसे सरल संभव तरीका है:

./A | ./B

अगर मुझे इस कमांड का वर्णन करना होता है, तो मैं कहूंगा कि यह एक कमांड है जो एक निर्माता से इनपुट (यानी, पढ़ता है A) और एक उपभोक्ता को लिखता है ( B)। क्या यह एक सही विवरण है? क्या मुझे कुछ याद आ रहा है?



यह कमांड नहीं है, यह बैश प्रक्रिया द्वारा बनाई गई एक किन्नर वस्तु है, जिसका उपयोग प्रक्रिया ए के स्टडआउट और बी के रूप में स्टड के रूप में किया जाता है। दो प्रक्रियाएं लगभग एक ही समय में शुरू की जाती हैं।
0 炸鱼 炸鱼

1
@ Object आप सही हैं - कर्नेल पाइपलाइन के लिए पिपिफ़ फाइलसिस्टम में एक वस्तु है, लेकिन जहाँ तक शेल स्वयं का संबंध है - तकनीकी रूप से यह एक पाइपलाइन कमांड है
सर्गी कोलोडियाज़नी

जवाबों:


26

आपके प्रश्न के बारे में केवल एक चीज जो गलत है, वह यह है कि आप कहते हैं

A पहले भागता है, फिर B को A का स्टैडआउट मिलता है

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

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

वर्णन करने के लिए मुहावरेदार तरीका A | Bयह है कि यह एक पाइपलाइन है जिसमें दो कार्यक्रम हैं। पहले कार्यक्रम से मानक आउटपुट पर उत्पादित आउटपुट दूसरे द्वारा मानक इनपुट पर पढ़ने के लिए उपलब्ध है ("[का आउटपुट] A[इनपुट के] B" में पाइप किया गया है )। शेल ऐसा करने की अनुमति देने के लिए आवश्यक प्लंबिंग करता है।

यदि आप "उपभोक्ता" और "निर्माता" शब्दों का उपयोग करना चाहते हैं, तो मुझे लगता है कि यह ठीक भी है।

तथ्य यह है कि ये सी में लिखे गए कार्यक्रम प्रासंगिक नहीं हैं। तथ्य यह है कि यह लिनक्स, macOS, OpenBSD या AIX प्रासंगिक नहीं है।


2
अस्थायी फ़ाइल में लिखने का उपयोग DOS में किया गया था, क्योंकि यह कई प्रक्रियाओं का समर्थन नहीं करता था।
सीएसएम

2
@AlexVong ध्यान दें कि एक अस्थायी फ़ाइल के साथ आपका उदाहरण बिल्कुल समकक्ष नहीं है। एक फ़ाइल की सामग्री के लिए एक कार्यक्रम चुन सकते हैं, लेकिन एक पाइप से आने वाले डेटा को खोजने योग्य नहीं है। mkfifoनामांकित पाइप बनाने के लिए एक बेहतर परीक्षा का उपयोग करना होगा , फिर पाइप से पृष्ठभूमि पढ़ने में बी शुरू करें, और फिर ए को लिखें । हालांकि यह प्रभाव से समान होगा।
Kusalananda

2
@AlexVong उस लेख में किए गए सरलीकरण वास्तविक पाइपलाइन से इसे तलाक देते हैं; समानांतर निष्पादन वास्तव में शब्दार्थ है, अनुकूलन नहीं। यह किसी ऐसे व्यक्ति के लिए मोनडिक मूल्यांकन या रचना का एक उचित झूठ-से-बच्चों का स्पष्टीकरण है जिसने शेल पाइपलाइनों को देखा है, लेकिन यह दूसरी दिशा में मान्य नहीं है। कुसलानंद का पेंडो संस्करण करीब है, लेकिन मॉडल के त्रुटि प्रसार भागों वास्तव में महत्वपूर्ण हैं और प्रतिकृति नहीं हैं। (सभी जो मैं कहता हूं कि कोई व्यक्ति जो "शेल पाइपलाइनों पर बहुत काम कर रहा है, बस रचना है")
माइकल होमर

6
@AlexVong नहीं, यह पूरी तरह से बंद है। यह भी सरल की तरह कुछ समझाने में सक्षम नहीं है yes | sed 10q
चाचा बिली

1
@UncleBilly मैं आपके उदाहरण से सहमत हूं। इससे पता चलता है कि माइकल द्वारा समानांतर निष्पादन की भी वास्तव में आवश्यकता है। अन्यथा, हम गैर-समाप्ति प्राप्त करेंगे।
एलेक्स वोंग

2

आमतौर पर प्रलेखन में उपयोग किया जाने वाला शब्द "पाइपलाइन" है, जिसमें एक या एक से अधिक कमांड होते हैं, POSIX परिभाषा देखें। इसलिए तकनीकी रूप से बोलना, कि आपके पास दो कमांड हैं, शेल के लिए दो उपप्रकार (या तो fork()+exec()'बाहरी बाहरी आदेश या उपधारा)

के रूप में निर्माता-उपभोक्त हिस्सा है, पाइप लाइन है कि पैटर्न द्वारा वर्णित किया जा सकता है, के बाद से:

  • निर्माता और उपभोक्ता निश्चित आकार के बफर को साझा करते हैं, और कम से कम लिनक्स और मैकओएस एक्स पर, पाइपलाइन बफर के लिए निश्चित आकार है
  • निर्माता और उपभोक्ता शिथिल-युग्मित हैं, पाइपलाइन में कमांड एक-दूसरे के अस्तित्व का पता नहीं लगाते हैं (जब तक कि वे सक्रिय रूप से /proc/<pid>/fdनिर्देशिका की जांच नहीं कर रहे हैं )।
  • निर्माता लिखते हैं stdoutऔर उपभोक्ताओं को पढ़ते हैं stdinजैसे कि वे एक ही आदेश को निष्पादित कर रहे थे, उर्फ ​​वे एक दूसरे के बिना मौजूद हो सकते हैं

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

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