फ़ाइल डिस्क्रिप्टर को वापस करने के लिए कांटा () क्यों बनाया गया है?


16

सेल्फ-पाइप ट्रिक के बारे में अपने वेब पेज पर , डैन बर्नस्टीन एक दौड़ की स्थिति और संकेतों के साथ बताते हैं , एक वर्कअराउंड प्रदान करते हैं और निष्कर्ष निकालते हैं किselect()

बेशक, राइट थिंग fork()एक फाइल डिस्क्रिप्टर को वापस करना होगा , न कि एक प्रक्रिया आईडी।

इसका क्या मतलब है - क्या यह select()उन राज्य परिवर्तनों को अधिसूचित करने के लिए सिग्नल हैंडलर का उपयोग करने के बजाय अपने राज्य परिवर्तनों को संभालने के लिए बाल प्रक्रियाओं पर सक्षम होने के बारे में कुछ है ?


क्या उस लेख में इनपुट और आउटपुट मिलाया गया है, या क्या मैं इसे सही नहीं पढ़ रहा हूं?
ctrl-alt-delor

आप पाइप पर वितरित किए जाने वाले संकेतों के लिए पूछ सकते हैं। यह वो है जो मैं करुंगा।
बजे ctrl-alt-delor

@ ctrl-alt-delor, हाँ, वह "पाइप इनपुट / आउटपुट" का उपयोग थोड़ा अजीब तरह से करता है, लेकिन मुझे लगता है कि यह स्पष्ट है कि वह कहाँ से लिख रहा है और पाइप से पढ़ रहा है। वह पाठ 2003 से है, और मुझे यकीन नहीं है कि signalfdएस और इस तरह से एक चीज वापस आ गई थी?
ilkachachu

5
डैन जानता है कि वह किस बारे में बात कर रहा है, हालांकि वह थोड़ा जानबूझकर उत्तेजक हो सकता है। अगर मुझे जानबूझकर उकसाया जा रहा है, तो मैं इसे स्पष्ट कर दूंगा, राइट थिंकिंग SIGCHLD से छुटकारा पाने के लिए होगी।
स्टीव समिट

1
@mosvy मैं थोड़ा अतिरंजित कर रहा हूं, लेकिन हर कार्यक्रम और हर प्रोग्रामर को मैंने कभी देखा है जिसने SIGCHLD का उपयोग करने की कोशिश की है, इसके साथ समस्याएं थीं। यह दौड़ की स्थिति होने की प्रतीक्षा कर रहा है। जब हम सभी को रोक wait()रहे थे, तो ऐसी चीजें थीं जो आप नहीं कर सकते थे, इसलिए किसी ने SIGCHLD का आविष्कार किया, लेकिन यह एक बुरा काम था। मेरे अनुभव में, और अब है कि वे मौजूद हैं, अच्छा छिड़काव, nonblocking wait3(), wait4(), और / या waitpid()प्रमुख स्थानों पर कॉल (शायद आपका मुख्य समारोह पाश) एक काफी बेहतर विकल्प नहीं है।
स्टीव समिट

जवाबों:


14

आपके स्रोत में समस्या का वर्णन select()किया गया है SIGCHLD, जैसे संकेतों से बाधित होना चाहिए , लेकिन कुछ मामलों में यह अच्छी तरह से काम नहीं करता है। तो वर्कअराउंड एक पाइप को सिग्नल राइट करना है, जिसे तब देखा जाता है select()। फ़ाइल डिस्क्रिप्टर देखना यह select()है कि समस्या के चारों ओर काम करता है।

वर्कअराउंड अनिवार्य रूप से सिग्नल इवेंट को फाइल डिस्क्रिप्टर इवेंट में बदल देता है। अगर fork()बस पहली जगह में एक एफडी लौटाया जाता है, तो वर्कअराउंड की आवश्यकता नहीं होगी, क्योंकि उस एफडी को तब सीधे उपयोग किया जा सकता है select()

तो हां, पिछले पैराग्राफ में आपका वर्णन मुझे सही लगता है।


एक और कारण है कि एक fd (या किसी अन्य प्रकार का कर्नेल हैंडल) एक सादे प्रक्रिया आईडी संख्या से बेहतर होगा, यह है कि PID प्रक्रिया के मरने के बाद पुन: उपयोग कर सकते हैं। कुछ मामलों में यह समस्या हो सकती है जब प्रक्रियाओं को सिग्नल भेजते हैं, तो यह सुनिश्चित करने के लिए पता करना संभव नहीं हो सकता है कि प्रक्रिया वह है जो आप सोचते हैं कि यह है, और एक ही पीआईडी ​​का पुन: उपयोग नहीं कर रहा है। (हालांकि मुझे लगता है कि यह एक बच्चे की प्रक्रिया को संकेत भेजते समय समस्या नहीं होनी चाहिए, क्योंकि माता-पिता को wait()अपने पीआईडी ​​को जारी करने के लिए बच्चे को चलाना होगा।)


उन्होंने कहा, मुझे ठीक से याद नहीं है कि मैंने PID के पुन: उपयोग के बारे में जो मामले पढ़े हैं, वह समस्या है, इसलिए यदि कोई भी उस पर विस्तृत या स्पष्टीकरण करना चाहता है, या उपरोक्त को संपादित करना चाहता है , तो ऐसा करने के लिए स्वतंत्र महसूस करें।
ilkachachu

2
जैसा कि आप पहले ही बता चुके हैं, माता-पिता के लिए कोई बहाना नहीं है कि उनका खुद का बच्चा पिड का पुन: उपयोग कर रहा है। यह उस स्थिति पर पूर्ण नियंत्रण रखता है क्योंकि यह वह है जो कॉल करता है wait()
जोशुआ

इन्हें ज़ोंबी प्रक्रिया कहा जाता है : "एक प्रक्रिया जिसने निष्पादन पूरा कर लिया है, लेकिन अभी भी प्रक्रिया तालिका में एक प्रविष्टि है: यह" समाप्त राज्य "में एक प्रक्रिया है। यह बाल प्रक्रियाओं के लिए होता है, जहां प्रवेश अभी भी माता-पिता को अनुमति देने के लिए आवश्यक है। अपने बच्चे के बाहर निकलने की स्थिति को पढ़ने की प्रक्रिया "
लस्सी

6
यह की कीमत का उल्लेख है कि अब लिनक्स कर सकते हैं से एक फ़ाइल वर्णनकर्ता (pidfd) वापसी cloneहै, जो वास्तविक सिस्टम कॉल लिनक्स पर कि कांटा का आह्वान है। इसे सक्षम करने के लिए ध्वज को कहा जाता है CLONE_PIDFD- उदाहरण के लिए देखें lwn.net/Articles/784831
केजे तानकटसिडिस

1
@Lie रयान, री " फोर्क () एक स्थानीय हैंडल के बजाय एक वैश्विक हैंडल लौटाता है , क्योंकि यह वैचारिक रूप से अधिक सही है ,", विंडोज हैंडल प्रोसेस हैंडल करता है। जब तक प्रक्रिया के सभी हैंडल बंद नहीं हो जाते, तब तक पिड और एग्जिट कोड चारों ओर से चिपका रहता है (बजाय रिक्शे के लिए माता-पिता की प्रतीक्षा करने के), दौड़ की परिस्थितियों से बचने के लिए यूनिक्स सिस्टम में आम है। जब हैंडल प्रक्रिया को जीवित रखते हैं, तो यह वैश्विक अर्थों के बजाय स्थानीय हैंडल होने के लिए कहीं अधिक समझ में आता है।
इकेगामी

9

यह "यूनिक्स की तुलना में अलग तरीके से डिजाइन किया गया है" तो यह बहुत अच्छा होगा।

पीआईडी ​​के साथ समस्या यह है कि वे एक वैश्विक नामस्थान में रहते हैं जहां उन्हें एक और प्रक्रिया के लिए पुन: उपयोग किया जा सकता है, और यह अच्छा होगा यदि fork()माता-पिता को किसी तरह के संभाल में लौटाया जाए जो हमेशा बच्चे की प्रक्रिया को संदर्भित करने की गारंटी होगी, और यह कि वंशानुक्रम या यूनिक्स सॉकेट / SCM_RIGHTS[1] के माध्यम से अन्य प्रक्रियाओं को पारित कर सकता है ।

लिनक्स को "ठीक" करने के हालिया प्रयास के लिए यहां चर्चा भी देखें , जिसमें एक ध्वज जोड़ना भी शामिल है, clone()जिसके कारण यह पीआईडी ​​के बजाय पीआईडी-एफडी लौटाएगा।

लेकिन फिर भी, यह उस आत्म-पाइप हैक [2] या बेहतर इंटरफेस की आवश्यकता को समाप्त नहीं करेगा, क्योंकि एक बच्चे की स्थिति के बारे में माता-पिता की प्रक्रिया को सूचित करने वाले संकेत केवल वे ही नहीं हैं जिन्हें आप मुख्य लूप में संभालना चाहते हैं। कार्यक्रम का। दुर्भाग्य से, epoll(7) + signalfd(2)लिनक्स या kqueue(2)बीएसडी जैसी चीजें मानक नहीं हैं - केवल मानक इंटरफ़ेस (लेकिन पुराने सिस्टम पर समर्थित नहीं) बहुत हीन है pselect(2)

[१] पीआईडी ​​को रोकना उस समय तक पुन: चक्रित होने से waitpid()बचा जब तक सीस्केल वापस आ गया था और इसके वापसी मूल्य का उपयोग किया गया था शायद waitid(.., WNOWAIT)इसके बजाय उपयोग करके नए सिस्टम पर प्राप्त किया जा सकता है ।

[२] मैं डीजे बर्नस्टीन के इस दावे पर टिप्पणी नहीं करूंगा कि उन्होंने इसका आविष्कार किया था (क्षमा याचना के लिए खेद ;-))।


8

बर्नस्टीन इस "राइट थिंग" टिप्पणी के लिए बहुत अधिक संदर्भ नहीं देता है, लेकिन मैं एक अनुमान लगाऊंगा: कांटा (2) रिटर्न एक पीआईडी ​​खुली (2), प्राणी (2) आदि रिटर्न फाइल डिस्क्रिप्टर के साथ असंगत है। बाकी यूनिक्स प्रणाली एक PID के बजाय एक प्रक्रिया का प्रतिनिधित्व करने वाले फ़ाइल डिस्क्रिप्टर के साथ प्रक्रिया हेरफेर कर सकती थी। एक सिस्टम कॉल सिग्नलफैड (2) मौजूद है, जो सिग्नल और फाइल डिस्क्रिप्टर के बीच कुछ बेहतर इंटरैक्शन की अनुमति देता है, और दिखाता है कि एक फाइल-डिस्क्रिप्टर-एक प्रक्रिया का प्रतिनिधित्व कर सकता है।


signalfd (2) भयानक लग रहा है, यह उल्लेख करने के लिए धन्यवाद! बहुत बुरा है यह केवल लिनक्स है।
लस्सी

1
pidfd_openलिनक्स में भी चर्चा हुई है , उदाहरण के लिए देखें lwn.net/Articles/789023
dhag
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.