जैसा कि दशूनून और चार्ली मार्टिन ने नोट किया, यह एक बड़ा सवाल है। उनके उत्तरों के कुछ हिस्से गलत हैं, इसलिए मैं भी जवाब देने जा रहा हूं।
मुझे अलग-अलग प्रोग्राम मॉड्यूल लिखने में दिलचस्पी है जो स्वतंत्र धागे के रूप में चलते हैं जिन्हें मैं पाइप के साथ जोड़ सकता हूं।
एक भी प्रक्रिया के धागे के बीच एक संचार तंत्र के रूप में पाइप का उपयोग करने की कोशिश कर रहा से सावधान रहें। क्योंकि आप दोनों एक ही प्रक्रिया में खुले पाइप के सिरों को पढ़ और लिखते हैं, तो आपको कभी भी ईओएफ (शून्य बाइट्स) संकेत नहीं मिलेगा।
तुम सच में प्रक्रियाओं की चर्चा करते हुए किया गया है, तो इस निर्माण उपकरण के लिए क्लासिक यूनिक्स दृष्टिकोण का आधार है। मानक यूनिक्स प्रोग्राम में से कई फ़िल्टर मानक हैं जो मानक इनपुट से पढ़ते हैं, इसे किसी भी तरह बदलते हैं, और मानक आउटपुट को परिणाम लिखते हैं। उदाहरण के लिए, tr
, sort
, grep
, और cat
सभी फिल्टर, नाम लेकिन कुछ कर रहे हैं। जब आप मैनिपुलेटिंग कर रहे हैं तो यह अनुपालन करने के लिए यह एक उत्कृष्ट प्रतिमान है। सभी डेटा मैनिप्ल्यूशन इस दृष्टिकोण के अनुकूल नहीं हैं, लेकिन ऐसे कई हैं।
प्रेरणा हो सकता है कि मैं लिख सकता है और पूरी तरह से स्वतंत्र रूप से प्रत्येक मॉड्यूल का परीक्षण, शायद यह भी उन्हें अलग अलग भाषाओं में लिखते हैं, या विभिन्न मशीनों पर विभिन्न मॉड्यूल चलाते हैं।
अच्छा अंक। , जानते हैं कि वास्तव में मशीनों के बीच एक पाइप कार्यप्रणाली नहीं है हो सकता है कि आप इस तरह के rsh
या (बेहतर) ssh
के रूप में कार्यक्रमों के साथ इसे करने के लिए करीब प्राप्त कर सकते हैं। हालांकि, आंतरिक रूप से, ऐसे कार्यक्रम पाइप से स्थानीय डेटा पढ़ सकते हैं और उस डेटा को दूरस्थ मशीनों पर भेज सकते हैं, लेकिन वे पाइप का उपयोग न करने वाले सॉकेट पर मशीनों के बीच संवाद करते हैं।
यहां संभावनाओं की एक विस्तृत विविधता हैं। मैंने थोड़ी देर के लिए पाइपिंग का उपयोग किया है, लेकिन मैं इसके व्यवहार की बारीकियों से अपरिचित हूं।
ठीक; प्रश्न पूछना सीखने के लिए एक (अच्छा) तरीका है। प्रयोग निश्चित रूप से एक और है।
ऐसा लगता है कि प्राप्त करने वाला अंत इनपुट के लिए इंतजार कर रहा है, जो मैं उम्मीद करता हूं, लेकिन कभी-कभी भेजना अंत ब्लॉक किसी को धारा से पढ़ने के लिए इंतजार कर रहा है?
हां। एक पाइप बफर के आकार की एक सीमा है। क्लासिकल, यह काफी छोटा था - 40 9 6 या 5120 आम मूल्य थे। आप पाते हैं कि आधुनिक लिनक्स एक बड़ा मूल्य का उपयोग करता है। आप पाइप बफर के आकार का पता लगाने के लिए fpathconf()
और _PC_PIPE_BUF का उपयोग कर सकते हैं। POSIX केवल बफर को 512 होने की आवश्यकता है (यानी, _POSIX_PIPE_BUF 512 है)।
यदि मैं धारा में एक ईओएफ लिखता हूं तो क्या मैं इसे बंद करने तक उस स्ट्रीम को लिखना जारी रख सकता हूं?
तकनीकी रूप से, स्ट्रीम में ईओएफ लिखने का कोई तरीका नहीं है; आप ईओएफ इंगित करने के लिए पाइप डिस्क्रिप्टर बंद करते हैं। यदि आप नियंत्रण-डी या नियंत्रण-जेड को ईओएफ चरित्र के रूप में सोच रहे हैं, तो वे केवल नियमित वर्ण हैं जहां तक पाइप का संबंध है - वे केवल ईओएफ की तरह प्रभाव डालते हैं जब टर्मिनल पर टाइप किया जाता है जो कैनोलिक मोड में चल रहा है (पकाया जाता है , या सामान्य)।
क्या नामित नाम और नामित पाइप में अंतर है?
हाँ, और नहीं। सबसे बड़ा अंतर यह है कि अज्ञात पाइप एक प्रक्रिया द्वारा स्थापित किए जाने चाहिए और केवल उस प्रक्रिया और बच्चों द्वारा उपयोग किया जा सकता है जो उस प्रक्रिया को एक सामान्य पूर्वजों के रूप में साझा करते हैं। इसके विपरीत, नामित पाइप का उपयोग पूर्व असंबद्ध प्रक्रियाओं द्वारा किया जा सकता है। अगला बड़ा अंतर पहले का परिणाम है; एक अनाम पाइप के साथ, आप वापस एक भी समारोह (प्रणाली) pipe()
करने के लिए कॉल से दो फ़ाइल वर्णनकर्ता मिलता है, लेकिन आप एक फीफो या नामित पाइप नियमित open()
समारोह का उपयोग कर खोलें।(किसी को इसे खोलने से पहले mkfifo()
कॉल के साथ एक फीफो बनाना होगा; अज्ञात पाइपों को ऐसे पूर्व सेटअप की आवश्यकता नहीं है।) हालांकि, एक बार जब आपके पास फ़ाइल डिस्क्रिप्टर खुलता है, तो नामित पाइप और एक अज्ञात पाइप के बीच मूल्यवान अंतर होता है ।
क्या इससे कोई फर्क पड़ता है कि मैंने पाइप के किस छोर को पहले नामित पाइप के साथ खोल दिया था?
नहीं। एफआईएफओ खोलने की पहली प्रक्रिया (सामान्य रूप से) ब्लॉक होगी जब तक कि दूसरी छोर के साथ कोई प्रक्रिया न हो। यदि आप इसे पढ़ने और लिखने के लिए खोलते हैं (आकस्मिक लेकिन संभव) तो आपको अवरुद्ध नहीं किया जाएगा; यदि आप O_NONBLOCK ध्वज का उपयोग करते हैं, तो आपको अवरुद्ध नहीं किया जाएगा।
विभिन्न लिनक्स सिस्टम के बीच लगातार पाइप के व्यवहार है?
हां। मैंने उन प्रणालियों पर पाइप के साथ किसी भी समस्या के बारे में सुना या अनुभव नहीं किया है जहां मैंने उनका उपयोग किया है।
क्या पाइप का व्यवहार उस खोल पर निर्भर करता है जिसका मैं उपयोग कर रहा हूं या जिस तरह से मैंने इसे कॉन्फ़िगर किया है?
नहीं: पाइप और FIFOs खोल आप उपयोग से स्वतंत्र हैं।
क्या कोई अन्य प्रश्न पूछना चाहिए या मुझे समस्याएं होनी चाहिए, मुझे इस बारे में पता होना चाहिए कि क्या मैं इस तरह से पाइप का उपयोग करना चाहता हूं?
बस याद रखें कि आपको प्रक्रिया में एक पाइप के पढ़ने के अंत को बंद करना होगा, और प्रक्रिया में पाइप के लेखन अंत को पढ़ना होगा। यदि आप पाइप पर द्विपक्षीय संचार चाहते हैं, तो दो अलग पाइप का उपयोग करें। यदि आप जटिल नलसाजी व्यवस्था बनाते हैं, तो डेडलॉक से सावधान रहें - यह संभव है। एक रैखिक पाइपलाइन डेडलॉक नहीं करती है, हालांकि (हालांकि अगर पहली प्रक्रिया कभी भी अपने आउटपुट को बंद नहीं करती है, तो डाउनस्ट्रीम प्रक्रियाएं अनिश्चित काल तक प्रतीक्षा कर सकती हैं)।
मैंने ऊपर और टिप्पणियों में दोनों उत्तरों को देखा कि पाइप बफर शास्त्रीय रूप से काफी छोटे आकार तक सीमित हैं। @ चार्ली मार्टिन ने टिप्पणी की कि यूनिक्स के कुछ संस्करणों में गतिशील पाइप बफर हैं और ये काफी बड़े हो सकते हैं।
मुझे यकीन नहीं है कि उनके मन में कौन सा है।
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
static const char *arg0;
static void err_syserr(char *str)
{
int errnum = errno;
fprintf(stderr, "%s: %s - (%d) %s\n", arg0, str, errnum, strerror(errnum));
exit(1);
}
int main(int argc, char **argv)
{
int pd[2];
pid_t kid;
size_t i = 0;
char buffer[2] = "a";
int flags;
arg0 = argv[0];
if (pipe(pd) != 0)
err_syserr("pipe() failed");
if ((kid = fork()) < 0)
err_syserr("fork() failed");
else if (kid == 0)
{
close(pd[1]);
pause();
}
/* else */
close(pd[0]);
if (fcntl(pd[1], F_GETFL, &flags) == -1)
err_syserr("fcntl(F_GETFL) failed");
flags |= O_NONBLOCK;
if (fcntl(pd[1], F_SETFL, &flags) == -1)
err_syserr("fcntl(F_SETFL) failed");
while (write(pd[1], buffer, sizeof(buffer)-1) == sizeof(buffer)-1)
{
putchar('.');
if (++i % 50 == 0)
printf("%u\n", (unsigned)i);
}
if (i % 50 != 0)
printf("%u\n", (unsigned)i);
kill(kid, SIGINT);
return 0;
}
मैं अन्य प्लेटफार्मों से अतिरिक्त परिणाम पाने के लिए उत्सुक हो जाएगा: मैं परीक्षण कार्यक्रम कि सोलारिस, AIX, HP-UX, MacOS X, लिनक्स और Cygwin/Windows XP (नीचे दिए गए परिणामों) पर इस प्रकार का इस्तेमाल किया। मुझे मिले आकार यहां दिए गए हैं। मेरे परिणाम अपेक्षा से बड़े हैं, मुझे कबूल करना होगा, लेकिन जब बफर आकार की बात आती है तो चार्ली और मैं 'काफी बड़े' के अर्थ पर बहस कर रहे हैं।
- 8196 - IA-64 के लिए HP-UX 11.23 (fcntl (F_SETFL) विफल)
- 16384 - Solaris 10
- 16384 - MacOS X 10.5 (O_NONBLOCK काम नहीं किया है, हालांकि fcntl (F_SETFL) असफल नहीं हुआ)
- 32768 - AIX 5।3
- 65536 - Cygwin/Windows XP (O_NONBLOCK, काम नहीं किया है, हालांकि fcntl (F_SETFL) असफल नहीं किया था)
- 65536 - SuSE Linux 10 (और CentOS) (fcntl (F_SETFL) में विफल रहा है)
इन बिंदुओं से स्पष्ट एक बिंदु यह है कि O_NONBLOCK कुछ प्लेटफ़ॉर्म पर पाइप के साथ काम करता है, न कि दूसरों पर।
कार्यक्रम एक पाइप, और कांटे बनाता है। बच्चा पाइप के लिखने के अंत को बंद कर देता है, और तब तक सो जाता है जब तक कि यह सिग्नल न हो जाए - यही कारण है() करता है। तब माता-पिता पाइप के पढ़ने के अंत को बंद कर देता है, और लिखने वाले वर्णनकर्ता पर झंडे सेट करता है ताकि वह पूर्ण पाइप पर लिखने के प्रयास पर रोक न सके। इसके बाद यह एक समय में एक चरित्र लिखता है, और प्रत्येक चरित्र के लिए एक बिंदु मुद्रित करता है, और प्रत्येक 50 वर्णों की गिनती और नई रेखा। जब यह एक लिखने की समस्या का पता लगाता है (बफर भरा हुआ है, चूंकि बच्चा कोई चीज़ नहीं पढ़ रहा है), यह लूप को रोकता है, अंतिम गिनती लिखता है, और बच्चे को मारता है।
stat() के साथ एक पाइप की सामग्री पर peeking सभी प्लेटफार्मों में भरोसेमंद नहीं है। –
पाइप बफर भरने पर लेखन अंत ब्लॉक कर सकता है - यह बहुत बड़ा नहीं है। –
क्रॉस-मशीन पाइप हैं ... मौजूद नहीं हैं? निकटतम दृष्टिकोण शायद एक सॉकेट है, लेकिन यह एक पाइप के समान नहीं है। –