dup2 / dup - मुझे फ़ाइल डिस्क्रिप्टर की नकल करने की आवश्यकता क्यों होगी?


85

मैं के उपयोग को समझने के लिए कोशिश कर रहा हूँ dup2और dup

आदमी पृष्ठ से:

DESCRIPTION

dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may
be used interchangeably. They share locks, file position pointers and
flags; for example, if the file position is modified by using lseek on
one of the descriptors, the position is also changed for the other.

The two descriptors do not share the close-on-exec flag, however.

dup uses the lowest-numbered unused descriptor for the new descriptor.

dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.  

RETURN VALUE

dup and dup2 return the new descriptor, or -1 if an error occurred 
(in which case, errno is set appropriately).  

मुझे उस सिस्टम कॉल की आवश्यकता क्यों होगी? फ़ाइल डिस्क्रिप्टर को डुप्लिकेट करने का उपयोग क्या है?

अगर मेरे पास फाइल डिस्क्रिप्टर है, तो मैं इसकी एक प्रतिलिपि क्यों बनाना चाहूंगा?

अगर आप समझा सकते हैं और मुझे एक उदाहरण दे सकते हैं, जहां dup2/ जहां dupइसकी आवश्यकता है, मैं सराहना करता हूं ।

धन्यवाद


कैसे आप बिना गोले की पाइपिंग कार्यक्षमता लागू करेगा dupया dup2? आपको कॉल करने की आवश्यकता है pipe(2)और फिर फाइल डिस्क्रिप्टर-ई में dupसे एक है जैसेSTDIN_FILENO
बेसिल स्टायरनेविच

जवाबों:


46

डुप सिस्टम कॉल एक मौजूदा फ़ाइल डिस्क्रिप्टर को डुप्लिकेट करता है, एक नया लौटाता है जो उसी अंतर्निहित I / O ऑब्जेक्ट को संदर्भित करता है।

इस तरह से आदेशों को लागू करने की अनुमति देता है:

ls existing-file non-existing-file > tmp1  2>&1

2> & 1 शेल को कमांड को एक फाइल डिस्क्रिप्टर 2 देने के लिए कहता है जो कि डिस्क्रिप्टर 1. का डुप्लिकेट है।
अब फोन करने के लिए त्रुटि संदेश ls पर गैर मौजूदा फ़ाइल और का सही उत्पादन ls पर मौजूदा फ़ाइल में दिखाई tmp1 फ़ाइल।

निम्न उदाहरण कोड एक पाइप के रीड एंड से जुड़े मानक इनपुट के साथ प्रोग्राम wc चलाता है।

int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = 0;
pipe(p);
if(fork() == 0) {
    close(STDIN); //CHILD CLOSING stdin
    dup(p[STDIN]); // copies the fd of read end of pipe into its fd i.e 0 (STDIN)
    close(p[STDIN]);
    close(p[STDOUT]);
    exec("/bin/wc", argv);
} else {
    write(p[STDOUT], "hello world\n", 12);
    close(p[STDIN]);
    close(p[STDOUT]);
}

बच्चा फ़ाइल डिस्क्रिप्टर 0 पर रीड एंड को डुप्लिकेट करता है, पी में फाइल डे स्क्रिप्टर्स को बंद करता है, और डब्ल्यूसी को निष्पादित करता है। जब wc अपने मानक इनपुट से पढ़ता है, तो यह पाइप से पढ़ता है।
यह इसी तरह से पाइपों को डुबकी का उपयोग करके कार्यान्वित किया जाता है, अच्छी तरह से कि डुबकी का एक उपयोग अब आप कुछ और बनाने के लिए पाइप का उपयोग करते हैं, जो सिस्टम कॉल की सुंदरता है, आप एक चीज का उपयोग करने के बाद एक और उपकरण का उपयोग करते हैं जो पहले से ही हैं, इन उपकरणों का उपयोग करके बनाया गया था कुछ और ऐसा ही है .. अंत में सिस्टम कॉल्स सबसे बुनियादी उपकरण हैं जो आपको कर्नेल में मिलते हैं

चियर्स :)


1
तो dupफोन करने वाले के लिए मददगार है न कि lsप्रोग्राम के लिए? dupअगर पहले से ही फ़ाइल तक पहुँच है तो क्या ls जैसे कार्यक्रम में उपयोग होने का कोई लाभ है ? उदाहरण के लिए, lsत्रुटियों को लिखता है 2जो हार्डकोड है, इसलिए मेरे पास उपभोक्ता के रूप में इसे ओवर-राइड करने का एक तरीका है ls। मुझे लगता है कि एक सूक्ष्म बिंदु नहीं है?
निशांत

2
आपका उदाहरण कार्यक्रम लगता है एक बग के लिए; आप कॉल कर रहे हैं, dup(p[STDIN])लेकिन फिर परिणाम निकाल रहे हैं। क्या आप उपयोग करना dup2(p[STDIN], 0)चाहते थे?
कुक्सप्लोन

1
@Quuxplusone dup"वर्तमान में प्रक्रिया द्वारा उपयोग में नहीं किया गया सबसे कम संख्या वाला विवरणक लौटाता है।" चूंकि fd 0 अभी बंद था, इसलिए dup0. लौटना चाहिए। dup2इस बारे में स्पष्ट है कि किस fd का उपयोग किया जाना चाहिए, बजाय इसके कि वह सबसे कम मुक्त fd का उपयोग करे, इसलिए मैं इसे पसंद करूंगा।
वोडिन

@Wodin: आह, मैं शर्त लगाता हूं कि ओपी क्या सोच रहा था। क्या मैं भी सही हूं, हालांकि, "बस बंद" रिश्तेदार है, और ओपी का कोड उपस्थिति की स्थिति में टूट सकता है, उदाहरण के लिए, समवर्ती धागे जो फाइलें भी खोल सकते हैं?
क्क्सप्लसोन

@Quuxplusone मुझे संदेह है कि आप सही हैं, लेकिन निश्चित रूप से नहीं जानते। लेकिन उस स्थिति में आपको अन्य समस्याएं होंगी। यदि आप स्टड को बंद कर देते हैं क्योंकि आप कहीं और से पढ़ना चाहते हैं और फिर आपके द्वारा करने से पहले एक अन्य थ्रेड फ़ाइल खोली जाती है, तो इसे fd 0. मिलेगा। यदि आप डुप 2 का उपयोग करते हैं, तो यह fd को बंद कर देगा कि दूसरा थ्रेड खुल गया है, इसलिए दूसरा थ्रेड अब आपके द्वारा खोली गई फ़ाइल को (और लेखन से) पढ़ रहा होगा। वैसे भी, अगर मुझे ठीक से याद है कि आपको exec*मल्टीथ्रेडेड प्रक्रिया से नहीं बुलाना चाहिए । लेकिन मैं कोई थ्रेडिंग विशेषज्ञ नहीं हूं :)
वोडिन

18

फ़ाइल डिस्क्रिप्टर को डुप्लिकेट करने का दूसरा कारण इसके साथ उपयोग करना है fdopenfcloseजो फाइल डिस्क्रिप्टर पास किया गया था fdopen, उसे बंद कर देता है , इसलिए यदि आप नहीं चाहते कि ओरिजिनल फाइल डिस्क्रिप्टर बंद हो, तो आपको dupपहले इसे डुप्लिकेट करना होगा ।


fdopen()ऐसा लगता है कि किसी फाइल डिस्क्रिप्टर की नकल नहीं होती है, यह सिर्फ यूजर स्पेस में बफर बनाता है।
एरिक वांग

3
आपने मेरे उत्तर को गलत बताया। मुद्दा यह है कि आप dupइसे पास करने fdopenसे पहले fd करना चाहते हैं क्योंकि fcloseयह इसे बंद कर देगा।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

1
@ theferrit32: यदि आप FILEstdio इंटरफेस के माध्यम से एक preexisting खुली फ़ाइल तक पहुंचने के लिए एक हैंडल आवंटित करते हैं, तो आपको उस हैंडल को डीलॉलेट करने के लिए कॉल fcloseकरना होगा FILE। यदि आप अंतर्निहित खुली फ़ाइल का उपयोग करते रहना चाहते हैं, या यदि आपका सॉफ़्टवेयर आर्किटेक्चर ऐसा है, तो फ़ाइल डिस्क्रिप्टर के लिए मूल "स्वामी" कोड होगा close, यह तथ्य जो fcloseआपके द्वारा सौंपे गए अंतर्निहित फ़ाइल डिस्क्रिप्टर को भी बंद कर देता fdopenहै, एक समस्या है। dupपास होने के लिए एक ही खुली फ़ाइल के लिए एक नया फ़ाइल डिस्क्रिप्टर बनाने के लिए उपयोग करके आप इस समस्या से बच सकते हैं fdopen, ताकि fcloseमूल एक को बंद न करें।
आर .. गिटहब स्टॉप हेल्पिंग ICE

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

1
@ConradMeyer: हाँ, इसे लगाने का एक बहुत अच्छा तरीका है, एक नोट के साथ कि FILEजब आप इसे स्वामित्व में ले जाते हैं, तो "स्वामित्व को स्थानांतरित करने" के लिए कोई ऑपरेशन नहीं होता है।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

4

किसी प्रक्रिया से आउटपुट को रीडायरेक्ट करने में सक्षम होने के लिए डुप का उपयोग किया जाता है।

उदाहरण के लिए, यदि आप किसी प्रक्रिया से आउटपुट को बचाना चाहते हैं, तो आप आउटपुट (fd = 1) को डुप्लिकेट करते हैं, आप डुप्लिकेट किए गए fd को किसी फ़ाइल में रीडायरेक्ट करते हैं, फिर प्रक्रिया को कांटा और निष्पादित करते हैं, और जब प्रक्रिया समाप्त हो जाती है, तो आप फिर से रीडायरेक्ट करते हैं आउटपुट के लिए fd बचाया।


4

डाप / डुप 2 से संबंधित कुछ बिंदुओं पर ध्यान दिया जा सकता है

dup / dup2 - तकनीकी रूप से उद्देश्य एक फाइल टेबल एंट्री को अलग-अलग हैंडल द्वारा एक प्रक्रिया के अंदर साझा करना है। (यदि हम डिस्क्रिप्टर को फोर्क कर रहे हैं तो बच्चे की प्रक्रिया में डिफ़ॉल्ट रूप से डुप्लिकेट किया गया है और फ़ाइल टेबल प्रविष्टि भी साझा की गई है)।

इसका मतलब है कि हमारे पास एक से अधिक फ़ाइल डिस्क्रिप्टर हो सकते हैं डुप्लिकेट / डुप 2 फ़ंक्शन का उपयोग करके एक सिंगल ओपन फ़ाइल टेबल प्रविष्टि के लिए संभवतः अलग-अलग विशेषताएँ सकती हैं

(हालांकि वर्तमान में केवल FD_CLOEXEC ध्वज एक फ़ाइल विवरणक के लिए एकमात्र विशेषता है) लगता है।

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

dup(fd) is equivalent to fcntl(fd, F_DUPFD, 0);

dup2(fildes, fildes2); is equivalent to 

   close(fildes2);
   fcntl(fildes, F_DUPFD, fildes2);

अंतर हैं (अंतिम के लिए) - दो गलत कॉलों के शामिल होने के बाद fcntl के बाद कुछ गलत मान beteen dup2 और fcntl के अलावा दो फ़ंक्शन कॉल शामिल हैं।

विवरण http://pubs.opengroup.org/onlinepubs/009695399/functions/d.html.html से चेक किया जा सकता है

उपयोग का एक उदाहरण -

एक शेल में नौकरी नियंत्रण को लागू करते समय एक दिलचस्प उदाहरण, जहां डूप / डुप 2 का उपयोग देखा जा सकता है .. नीचे दिए गए लिंक पर

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

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