हमें निष्पादन कार्यों में फ़ाइल नाम दो बार पास क्यों करना पड़ता है?


12

मैंने स्टीवंस द्वारा 8 वें अध्याय में UNIX पर्यावरण में उन्नत प्रोग्रामिंग पढ़ा । मैं सभी छह निष्पादन क्रियाओं को पढ़ता और समझता हूं।

सभी निष्पादन कार्यों में एक बात मुझे ध्यान में है:

  • पहला तर्क फ़ाइल का नाम / पथ नाम (निष्पादन फ़ंक्शन पर निर्भर करता है) है।
  • दूसरा तर्क argv है [0] जो हमें मिलता है main(), जो कि फ़ाइल का नाम है।

इसलिए यहां हमें फंक्शन में फाइल का नाम दो बार पास करना होगा।

क्या इसका कोई कारण है (जैसे हम पहले तर्क से पथ के नाम से फ़ाइल नाम नहीं प्राप्त कर सकते हैं)?

जवाबों:


15

इसलिए यहां हमें फंक्शन में फाइल का नाम दो बार पास करना होगा।

वे बिल्कुल वैसी बात नहीं हैं जैसा कि आप देखते हैं कि उनमें से एक का उपयोग argv[0]मूल्य के रूप में किया जाता है । यह निष्पादन योग्य के आधार के समान नहीं है; कई / अधिकांश चीजें इसे नजरअंदाज करती हैं और आप जो चाहें वहां डाल सकते हैं।

पहला निष्पादन के लिए वास्तविक मार्ग है, जिसके लिए एक स्पष्ट आवश्यकता है। दूसरे को प्रक्रिया के लिए तीव्रता से पारित किया जाता है क्योंकि नाम इसे लागू करने के लिए उपयोग किया जाता है, लेकिन, जैसे:

execl("/bin/ls", "banana", "-l", NULL);

ठीक काम करेगा, अनुमान /bin/lsसही तरीका है।

कुछ अनुप्रयोग, हालांकि, का उपयोग करते हैं argv[0]। आमतौर पर इनमें एक या एक से अधिक सीलिंक होते हैं $PATH; यह संपीड़न उपयोगिताओं के साथ आम है (कभी-कभी वे इसके बजाय शेल रैपर का उपयोग करते हैं)। यदि आपने xzस्थापित किया है, तो stat $(which xzcat)यह एक लिंक दिखाता है xz, और man xzcatयह वही है man xzजो बताता है कि "xzcat xz --decompress --stdout के बराबर है"। जिस तरह से xz यह बता सकता है कि यह कैसे चेक किया गया था argv[0], इन बराबर कर रहा है:

execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);

5
आह, तो इससे यह पता चलेगा busyboxकि आप कैसे चाहते हैं कि आप इसे सही कैसे कहें?
terdon

4
@terdon यही कारण है कि बिजीबॉक्स के लिए सिंगल बाइनरी इतने सारे अलग-अलग कमांड को संतुष्ट करता है।
महिंद्रा

7
इसका मतलब यह होगा कि अगर /bin/lsव्यस्त था, तो यह नहीं पता होगा कि कैसे निष्पादित किया जाए banana!
राइजिंग

6

आपको फ़ाइल का नाम दो बार पास करने की आवश्यकता नहीं है।

पहला एक फ़ाइल है जो वास्तव में निष्पादित है।

दूसरा तर्क यह है कि argv[0]प्रक्रिया का क्या होना चाहिए , अर्थात प्रक्रिया को उसके नाम के रूप में क्या देखना चाहिए। उदाहरण के लिए, यदि आप lsशेल से चलते हैं, तो पहला तर्क है /bin/ls, दूसरा है ls

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


वास्तव में लिंक वही विधि है जो argv[0]लिंक नाम से सेट होती है।
गोल्डीलॉक्स

अंतिम पैराग्राफ में, "आप एक निश्चित फ़ाइल को निष्पादित कर सकते हैं और दूसरे तर्क के माध्यम से इसे कुछ और कह सकते हैं; कार्यक्रम इसके नाम की जांच कर सकता है और नाम के अनुसार 'अलग तरह से व्यवहार कर सकता है"। क्या आप कृपया मुझे विस्तृत कर सकते हैं या कुछ रीडिंग दे सकते हैं, मैं इस माहौल में एक नया हूँ।
मुंजाल ०

गोल्डीलॉक्स के उत्तर का अंतिम भाग यह बताता है।
wurtel

1

Takeaway है कि argv[0]कुछ भी (सहित NULL) के लिए सेट किया जा सकता है । अधिवेशन द्वारा , argv[0]निष्पादन योग्य पथ के रूप में आरंभ किया गया था (शेल प्रक्रिया द्वारा जब यह होता है execve()) पर सेट किया जाएगा।

तो ./fooऔर dir/barएक ही निष्पादन के लिए दो अलग-अलग लिंक (हार्ड या प्रतीकात्मक) कर रहे हैं, तो दो रास्तों का उपयोग कर सेट हो जाएगा खोल से कार्यक्रम शुरू argv[0]करने के लिए ./fooऔर dir/barक्रमश:।

इस तथ्य को अक्सर अनदेखा argv[0]किया जा सकता NULLहै। निम्न कोड NULL argv[0]उदाहरण के लिए क्रैश हो सकता है (हालांकि glibc इसके बजाय <null> जैसे कुछ प्रिंट करता है argv[0]):

if (argc != 3) {
    fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
    exit(EXIT_FAILURE);
}

लिनक्स पर एक विकल्प /proc/self/exeऐसे मामलों के लिए उपयोग करना है।


आप argv [0] दोनों को कैसे सेट कर सकते हैं ।/foo और dir / bar
munjal007

@ munjal007 मुझे क्षमा करें यदि मैं अस्पष्ट था। मेरा मतलब था दो बार कार्यक्रम चलाना: एक बार जैसा ./fooऔर एक बार dir/barargv[0]उन दो मामलों के लिए अलग होगा (प्रत्येक मामले में यह आपके द्वारा उपयोग किए गए पथ के समान होगा)।
उल्फालाइज़र

@ munjal007 यह मानते हुए कि आप इसे पाठ्यक्रम के खोल से चलाते हैं। मुद्दा यह है कि argv[0]जब आप exec*()स्वयं प्रोग्राम करते हैं तो आप कुछ भी सेट कर सकते हैं । यह argv[0]उस पथ को सेट करने का एक सम्मलेन है जिसका उपयोग कार्यक्रम को शुरू करने के लिए किया गया था (और जब आप exec*()प्रोग्राम करते हैं तो ऐसा ही करना बुद्धिमान होता है , क्योंकि कई कार्यक्रम निरीक्षण करते हैं argv[0]और यह उम्मीद करते हैं कि वह रास्ता पकड़ सके)।
उल्फालाइज़र
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.