2009-10-28 15 views
24

मेरे पास दो प्रोग्राम, लेखक और पाठक हैं।यूनिक्स पर कई पाठकों के साथ नामित पाइप्स (एफआईएफओ)

मेरे पास राइटर से रीडर तक एक फीफो है इसलिए जब मैं राइटर में stdin को कुछ लिखता हूं, तो इसे रीडर से stdout पर मुद्रित किया जाता है।

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

क्या कोई जानता है कि ऐसा क्यों होता है?

यदि मेरे पास दो WRITER प्रोग्राम हैं, तो वे दोनों एक ही पाइप को ठीक से लिखते हैं।

+0

क्या आप जानना चाहते हैं कि डेटा प्रत्येक पाठक को "प्रसारण" क्यों नहीं किया जाता है या क्यों डेटा प्रत्येक पाठक के बीच समान रूप से वितरित नहीं किया जाता है? – Jacob

+0

मुझे विश्वास है कि लेखक अपने stdout (stdin नहीं) पर लिख रहा है, जो फीफो है; प्रत्येक पाठक संभवतः इसे अपने स्वयं के stdin से पढ़ रहा है, जो फीफो है, और उसके बाद डेटा को अपने स्वयं के stdout पर लिख रहा है। –

+0

जैकब - मैं जानना चाहता हूं कि डेटा दोनों पाठकों के लिए क्यों नहीं जा रहा है, केवल एक। –

उत्तर

21

ओ एफआईएफ का मतलब है "बाहर"। एक बार आपका डेटा "बाहर" हो जाने पर, यह चला गया है। :-) तो स्वाभाविक रूप से यदि कोई और प्रक्रिया आती है और किसी और ने पहले ही पढ़ा है, तो डेटा दो बार नहीं होगा।

जो भी आप सुझाव देते हैं उसे पूरा करने के लिए आपको यूनिक्स डोमेन सॉकेट में देखना चाहिए। मैनपेज here। आप एक सर्वर लिख सकते हैं जो क्लाइंट प्रक्रियाओं को लिख सकता है, जो फाइल सिस्टम पथ पर बाध्यकारी है। socket(), bind(), listen(), accept(), connect(), जिनमें से आप PF_UNIX, AF_UNIX, और struct sockaddr_un के साथ उपयोग करना चाहते हैं।

+0

आह! यह वह है जिसका मैंने अंदाज़ लगाया था। स्पष्टीकरण के लिए धन्यवाद! –

2

मुझे नहीं लगता कि आपके द्वारा देखा गया व्यवहार संयोग से अधिक है। इस का पता लगाने, का उपयोग करता है जो दो पाठकों और लेखक के रूप में एक पाश के रूप में 'sed' पर विचार करें:

Osiris JL: mkdir fifo 
Osiris JL: cd fifo 
Osiris JL: mkfifo fifo 
Osiris JL: sed 's/^/1: /' < fifo & 
[1] 4235 
Osiris JL: sed 's/^/2: /' < fifo & 
[2] 4237 
Osiris JL: while read line ; do echo $line; done > fifo < /etc/passwd 
1: ## 
1: # User Database 
1: # 
1: # Note that this file is consulted directly only when the system is running 
1: # in single-user mode. At other times this information is provided by 
1: # Open Directory. 
1: # 
1: # This file will not be consulted for authentication unless the BSD local node 
1: # is enabled via /Applications/Utilities/Directory Utility.app 
1: # 
1: # See the DirectoryService(8) man page for additional information about 
1: # Open Directory. 
1: ## 
1: nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false 
1: root:*:0:0:System Administrator:/var/root:/bin/sh 
1: daemon:*:1:1:System Services:/var/root:/usr/bin/false 
1: _uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico 
1: _lp:*:26:26:Printing Services:/var/spool/cups:/usr/bin/false 
2: _postfix:*:27:27:Postfix Mail Server:/var/spool/postfix:/usr/bin/false 
2: _mcxalr:*:54:54:MCX AppLaunch:/var/empty:/usr/bin/false 
2: _pcastagent:*:55:55:Podcast Producer Agent:/var/pcast/agent:/usr/bin/false 
2: _pcastserver:*:56:56:Podcast Producer Server:/var/pcast/server:/usr/bin/false 
2: _serialnumberd:*:58:58:Serial Number Daemon:/var/empty:/usr/bin/false 
2: _devdocs:*:59:59:Developer Documentation:/var/empty:/usr/bin/false 
2: _sandbox:*:60:60:Seatbelt:/var/empty:/usr/bin/false 
2: _mdnsresponder:*:65:65:mDNSResponder:/var/empty:/usr/bin/false 
2: _ard:*:67:67:Apple Remote Desktop:/var/empty:/usr/bin/false 
2: _www:*:70:70:World Wide Web Server:/Library/WebServer:/usr/bin/false 
2: _eppc:*:71:71:Apple Events User:/var/empty:/usr/bin/false 
2: _cvs:*:72:72:CVS Server:/var/empty:/usr/bin/false 
2: _svn:*:73:73:SVN Server:/var/empty:/usr/bin/false 
2: _mysql:*:74:74:MySQL Server:/var/empty:/usr/bin/false 
2: _sshd:*:75:75:sshd Privilege separation:/var/empty:/usr/bin/false 
2: _qtss:*:76:76:QuickTime Streaming Server:/var/empty:/usr/bin/false 
2: _cyrus:*:77:6:Cyrus Administrator:/var/imap:/usr/bin/false 
2: _mailman:*:78:78:Mailman List Server:/var/empty:/usr/bin/false 
2: _appserver:*:79:79:Application Server:/var/empty:/usr/bin/false 
2: _clamav:*:82:82:ClamAV Daemon:/var/virusmails:/usr/bin/false 
2: _amavisd:*:83:83:AMaViS Daemon:/var/virusmails:/usr/bin/false 
2: _jabber:*:84:84:Jabber XMPP Server:/var/empty:/usr/bin/false 
2: _xgridcontroller:*:85:85:Xgrid Controller:/var/xgrid/controller:/usr/bin/false 
2: _xgridagent:*:86:86:Xgrid Agent:/var/xgrid/agent:/usr/bin/false 
2: _appowner:*:87:87:Application Owner:/var/empty:/usr/bin/false 
2: _windowserver:*:88:88:WindowServer:/var/empty:/usr/bin/false 
2: _spotlight:*:89:89:Spotlight:/var/empty:/usr/bin/false 
2: _tokend:*:91:91:Token Daemon:/var/empty:/usr/bin/false 
2: _securityagent:*:92:92:SecurityAgent:/var/empty:/usr/bin/false 
2: _calendar:*:93:93:Calendar:/var/empty:/usr/bin/false 
2: _teamsserver:*:94:94:TeamsServer:/var/teamsserver:/usr/bin/false 
2: _update_sharing:*:95:-2:Update Sharing:/var/empty:/usr/bin/false 
2: _installer:*:96:-2:Installer:/var/empty:/usr/bin/false 
2: _atsserver:*:97:97:ATS Server:/var/empty:/usr/bin/false 
2: _unknown:*:99:99:Unknown User:/var/empty:/usr/bin/false 
Osiris JL: jobs 
[1]- Running     sed 's/^/1: /' < fifo & 
[2]+ Done     sed 's/^/2: /' < fifo 
Osiris JL: echo > fifo 
1: 
Osiris JL: jobs 
[1]+ Done     sed 's/^/1: /' < fifo 
Osiris JL: 

आप देख सकते हैं, दोनों पाठकों डेटा के कुछ पढ़ने के लिए मिला है। कौन सा पाठक किसी भी समय ओ/एस के आधार पर निर्भर था। ध्यान दें कि मैंने फ़ाइल की प्रत्येक पंक्ति को मुद्रित करने के लिए सावधानी से एक गूंज का उपयोग किया; वे परमाणु लिखते थे जो परमाणु रूप से पढ़े गए थे।

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

perl -n -e 'while(<>){ print "1: $_"; sleep 1; }' < fifo & 
perl -n -e 'while(<>){ print "2: $_"; sleep 2; }' < fifo & 

मैकोज़ एक्स 10.5.8 (तेंदुए) पर प्रयोग किया गया - लेकिन यह अधिकतर स्थानों की संभावना है।

+0

ओह, और इसके लायक होने के लिए, जब मैंने दोनों पाठक स्क्रिप्ट में 'नींद 1' के साथ पर्ल संस्करण की कोशिश की, तो सब कुछ एक रन पर पाठक 2 द्वारा संसाधित हो गया। मैंने सिस्टम के हाथ को मजबूर करने के लिए असममित नींद डाली। –

+0

यह दिलचस्प है ... ऐसा लगता है जैसे एक पाठक फीफो से पढ़ता है, डेटा मिटा दिया जाता है और इसलिए अन्य पाठक एक ही डेटा नहीं पढ़ सकते हैं। –

+0

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

10

लिनक्स टीई() आपकी आवश्यकताओं के अनुरूप हो सकता है।
यहाँ tee

नोट देखें: इस समारोह लिनक्स विशिष्ट है।

+1

'टीई 'लिनक्स विशिष्ट नहीं है http://www.opengroup.org/onlinepubs/9699919799/utilities/tee.html; लेकिन मुझे यकीन नहीं है कि क्या यह मूल प्रश्न –

+2

में उपयोग के मामले में मदद करेगा, मैं सी फंक्शन टी का जिक्र कर रहा था, कमांड/अल्ट्रीली टी नहीं। लेकिन हाँ, मुझे यकीन नहीं है कि यह फ़ंक्शन अन्य प्लेटफ़ॉर्म/लाइब्रेरी पर लागू किया गया था या नहीं। – Julian

+0

टीई महान है। कठिन हिस्सा यह है कि, आपने अपनी डेटा स्ट्रीम को 30 प्रीकोसेस में टेड करने के बाद, ताकि वे डेटा के 1/30 वें प्रक्रिया को संसाधित कर सकें ... आप परिणामों को कैसे इकट्ठा करते हैं ... इसके लिए आपको 1 पाठक और कई लेखकों की आवश्यकता होती है। यह चाल 30 फीट बनाने के लिए है, और पाठक को "आउटपुट" है, जो पूरे आउटपुट में पढ़ रहा है। हैडूप को यह आपके लिए ऐसा माना जाता है लेकिन यह एक टेरेबल, ब्लोटेड फ्रेमवर्क है। 0 एमक्यू जैसे उपकरण हल्के/साफ आईपीसी करते हैं जो अधिकांश भाषाओं के साथ काम करता है। –

1

मैं उपर्युक्त स्पष्टीकरण में लिखना चाहता हूं जो लिखता है (और अनुमानित पढ़ता है, हालांकि मैं इसे मैनपेज से पुष्टि नहीं कर सकता) पाइप पर एक निश्चित आकार (लिनक्स पर 4KiB) पर परमाणु हैं। तो मान लें कि हम एक खाली पाइप से शुरू करते हैं, और लेखक < = 4KiB डेटा पाइप पर लिखते हैं। यहां मुझे लगता है कि ऐसा होता है:

ए) लेखक एक ही समय में सभी डेटा लिखता है। हालांकि यह हो रहा है कि किसी अन्य प्रक्रिया को पाइप से पढ़ने (या लिखने) का मौका नहीं है।

बी) पाठकों में से एक यह I/O करने के लिए निर्धारित है।

सी) चयनित पाठक एक ही समय में पाइप से सभी डेटा पढ़ता है, और कुछ समय बाद उन्हें अपने stdout पर प्रिंट करता है।

मुझे लगता है कि यह केवल तब तक समझा सकता है जब आप पाठकों में से केवल एक आउटपुट देख रहे हों। छोटे टुकड़ों में लिखने का प्रयास करें, और शायद प्रत्येक लेखन के बाद सो जाओ।

बेशक, दूसरों ने जवाब दिया है कि प्रत्येक डेटाम केवल प्रक्रिया द्वारा क्यों पढ़ा जाता है।

+0

* लेखक एक ही समय में सभी डेटा लिखता है। हालांकि यह हो रहा है कि किसी अन्य प्रक्रिया को पाइप से पढ़ने (या लिखने) का मौका नहीं है। * लिनक्स में निश्चित रूप से झूठा। एक पाठक पाइप से पढ़ता है जब तक लेखक ब्लॉक करेगा। तो पढ़ता है और लिखता है हमेशा समय में ओवरलैप (इस तरह से परमाणुता को नुकसान नहीं पहुंचाता है)। – DepressedDaniel

संबंधित मुद्दे