c++ - क्या किसी प्रोग्राम के अंदर से प्रोग्राम को रिस्टार्ट करना संभव है?




application-restart (6)

अनमैरिक्स पर, या कहीं और आपने execve और यह काम करता है जैसे मैन पेज निर्दिष्ट करता है , आप बस कर सकते हैं ... execve का उपयोग करने के लिए मुझे मार दें, क्योंकि यह आम तौर पर भयानक है, इस तरह के मामले को छोड़कर।

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char** argv) {

  (void) argc;

  printf("arg: %s\n", argv[1]);
  int count = atoi(argv[1]);

  if ( getchar() == 'y' ) {

    ++count;

    char buf[20];
    sprintf(buf, "%d", count);

    char* newargv[3];
    newargv[0] = argv[0];
    newargv[1] = buf;
    newargv[2] = NULL;

    execve(argv[0], newargv, NULL);
  }

  return count;
}

उदाहरण:

$ ./res 1
arg: 1
y
arg: 2
y
arg: 3
y
arg: 4
y
arg: 5
y
arg: 6
y
arg: 7
n

7 | $

(7 रिटर्न कोड था)।

यह न तो पुनरावृत्ति करता है और न ही स्पष्ट रूप से लूप करता है - इसके बजाय, यह केवल खुद को बुलाता है, अपने स्वयं के मेमोरी स्पेस को स्वयं के नए संस्करण के साथ बदल देता है।

इस तरह, स्टैक कभी भी अतिप्रवाह नहीं होगा, हालांकि सभी पिछले चर को फिर से जोड़ा जाएगा, जैसे कि किसी भी पुनर्निवेश के साथ - गेटच कॉल 100% सीपीयू उपयोग को रोकता है।

एक स्व-अद्यतन बाइनरी के मामले में, चूंकि संपूर्ण बाइनरी (कम से कम, यूनिक्स-लाइक पर, मुझे विंडोज के बारे में नहीं पता है) रनटाइम पर मेमोरी में कॉपी किया जाएगा, फिर यदि फ़ाइल execve(argv[0], ... होने से पहले डिस्क पर बदल execve(argv[0], ... कॉल, डिस्क पर पाया गया नया बाइनरी, वही पुराना नहीं, इसके बजाय चलाया जाएगा।

जैसा कि @CarstenS और @bishop ने यूनिक्स को डिजाइन करने के अनूठे तरीके के कारण टिप्पणियों में इंगित किया है, खुले फ़ाइल execve को fork / exec पार रखा जाता है, और परिणामस्वरूप, execve करने के लिए कॉलों पर खुली फ़ाइल विवरणों को लीक करने से बचने के लिए, आपको या तो execve करने से पहले उन्हें बंद करना चाहिए या उन्हें पहले से execve चाहिए, FD_CLOEXEC / O_CLOEXEC पहली जगह में - डैन वॉल्श के ब्लॉग पर अधिक जानकारी प्राप्त की जा सकती है।

मैं एक C ++ प्रोग्राम विकसित कर रहा हूं और यह कुछ फ़ंक्शन, स्क्रिप्ट या कुछ का उपयोग करने के लिए उपयोगी होगा जो प्रोग्राम को पुनरारंभ करता है। यह एक बड़ा कार्यक्रम है इसलिए मैन्युअल रूप से सभी चर को फिर से शुरू करने में मुझे लंबा समय लगेगा ...

मुझे नहीं पता कि इसे प्राप्त करने का कोई तरीका है या यदि यह संभव है।


आप अपने main कार्य में एक लूप का उपयोग कर सकते हैं:

int main()
{
    while(!i_want_to_exit_now) {
        // code
    }
}

या, यदि आप वास्तव में प्रोग्राम को पुनरारंभ करना चाहते हैं, तो इसे एक हार्नेस से चलाएं:

program "[email protected]"
while [ $? -e 42 ]; do
    program "[email protected]"
done

जहां 42 एक रिटर्न कोड है जिसका अर्थ है "पुनः आरंभ करें, कृपया"।

फिर प्रोग्राम के अंदर आपका restart फंक्शन इस तरह दिखेगा:

void restart() {
    std::exit(42);
}

कार्यक्रम को "पुनरारंभ" करने से आपका क्या मतलब है, इसके आधार पर मैं कुछ सरल समाधान देख सकता हूं।

एक को अपने पूरे कार्यक्रम को कुछ "प्रोग्राम" वर्ग में एम्बेड करना है, जो अनिवार्य रूप से कुछ लूप प्रदान करता है जिसमें आपका उचित कार्यक्रम है। जब आपको प्रोग्राम को पुनरारंभ करने की आवश्यकता होती है, तो आप लूप को फिर से शुरू करने वाले स्थिर सार्वजनिक विधि "रिस्टार्ट" कहते हैं।

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

अन्य सरल विकल्प goto का उपयोग करना है। मुझे पता है कि लोग इसका उल्लेख करने के लिए भी मुझसे नफरत करेंगे, लेकिन इसका सामना करना चाहिए: हम साधारण प्रोग्राम बनाना चाहते हैं, न कि सुंदर बॉयलरप्लेट का उपयोग करना। गोटो वापस जाना विनाश की गारंटी देता है , इसलिए आप शुरुआत में एक लेबल के साथ एक कार्यक्रम बना सकते हैं, और कुछ फ़ंक्शन "पुनः आरंभ करें" जो अभी शुरुआत में वापस जाता है।

आप जो भी विकल्प चुनते हैं, उसे अच्छी तरह से प्रलेखित करें, इसलिए अन्य (या आप भविष्य में) एक डब्ल्यूटीएफ का कम उपयोग करेंगे।

पुनश्च। जैसा कि alain ने उल्लेख किया है, goto वैश्विक और न ही स्थिर वस्तुओं को नष्ट नहीं करेगा, वही वर्ग को घेरने के लिए जाएगा। इसलिए कोई भी दृष्टिकोण जिसमें वर्तमान के स्थान पर नए कार्यक्रम को शुरू करना शामिल नहीं है, उसे या तो वैश्विक / स्थैतिक चर का उपयोग करने से बचना चाहिए, या उन्हें फिर से सेट करने के लिए उचित कार्रवाई करनी चाहिए (हालांकि यह थकाऊ हो सकता है, जैसा कि प्रत्येक स्थैतिक / वैश्विक के अतिरिक्त है , आपको पुनरारंभ दिनचर्या को संशोधित करने की आवश्यकता है)।


जब मैं रियलटाइम सिस्टम विकसित करता हूं, तो मेरा दृष्टिकोण आम तौर पर "व्युत्पन्न मुख्य ()" होता है, जहां मैं एक वास्तविक मुख्य से बुलाए गए सभी कोड लिखता हूं (), कुछ इस प्रकार है:

Main.cpp कार्यक्रम:

int main (int argc, char *argv[])
{
   while (true)
   {
       if (programMain(argc, argv) == 1)
           break;
   }
}

Programmain.cpp, जहाँ सभी कोड लिखे गए हैं:

int programMain(int argc, char *argv[])
{
    // Do whatever - the main logic goes here

    // When you need to restart the program, call
    return 0;

    // When you need to exit the program, call
    return 1;
}

इस तरह, हर बार जब हम कार्यक्रम से बाहर निकलने का निर्णय लेते हैं तो कार्यक्रम फिर से शुरू हो जाएगा।

विवरण: सभी चर, programMain() और लॉजिक को programMain() अंदर लिखा जाना चाहिए programMain() - पुनरारंभ नियंत्रण के अलावा "main()" अंदर कुछ भी नहीं।

यह दृष्टिकोण लिनक्स और विंडोज सिस्टम दोनों में काम करता है।


यह एक बहुत ही ओएस-विशिष्ट प्रश्न है। विंडोज में आप एप्लिकेशन रिस्टार्ट एपीआई या एमएफसी रिस्टार्ट मैनेजर का उपयोग कर सकते हैं। लिनक्स में आप एक exec() कर सकते हैं exec()

हालांकि ज्यादातर समय बेहतर समाधान होता है। जैसा कि आप अन्य उत्तर में सुझाए गए हैं, लूप का उपयोग करना बेहतर होगा।


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

इसके बजाय, आपका राज्य वस्तुओं में (वर्ग प्रकार का, या जो कुछ भी) होना चाहिए। आप जब चाहें तब इन वस्तुओं को बनाने और नष्ट करने के लिए स्वतंत्र हैं। प्रत्येक नई वस्तु में "डिफ़ॉल्ट" मानों के साथ एक ताज़ा स्थिति होती है।

सी ++ से मत लड़ो; इसका इस्तेमाल करें!






application-restart