2013-02-27 21 views
6

के साथ स्टैक को ऊपर/नीचे स्विच करना मैं समझने की कोशिश कर रहा हूं कि getcontext/setcontext किसी विशिष्ट परिदृश्य में सही तरीके से काम करेगा या नहीं।getcontext/setcontext

मैं देख सकता हूं कि कैसे इतिहास में किसी निश्चित स्थान पर स्टैक को खोलने के लिए setcontext() का उपयोग किया जा सकता है।

#include <stdio.h> 
#include <ucontext.h> 

int rollback = 0; 
ucontext_t context; 

void func(void) 
{ 
    setcontext(cp); 
} 

int main(void) 
{ 
    getcontext(&context); 
    if (rollback == 0) 
    { 
     printf("getcontext has been called\n"); 
     rollback++; 
     func(); 
    } 
    else 
    { 
     printf("setcontext has been called\n"); 
    } 
} 

लेकिन मैं सोच रहा था कि क्या एक अनचाहे के बाद आप भविष्य में किसी स्थान पर वापस लौट सकते हैं? मुझे लगता है कि यह getcontext() कॉल पर निर्भर करता है स्टैक की एक प्रति कैप्चर करता है और मुझे दस्तावेज़ में सटीक विवरण नहीं मिल रहा है।

#include <stdio.h> 
#include <ucontext.h> 

int rollback  = 0; 
int backToFuture = 0; 
ucontext_t context; 
ucontext_t futureContext; 

void func(void) 
{ 
    // Some complex calc 
    if (some-condition) 
    { 
     getcontext(&futureContext); // After returning I want to come back 
            // here to carry on with my work. 
     if (backToFuture == 0) 
     { 
      setcontext(&context); // rewind to get stuff-done 
     } 
    } 
    // Finishe work 
} 

int main(void) 
{ 
    getcontext(&context); 
    if (rollback == 0) 
    { 
     printf("getcontext has been called\n"); 
     rollback++; 
     func(); 

     // eventually always return here. 
    } 
    else 
    { 
     printf("setcontext has been called\n"); 
     // Do specialized work that needed to be done 
     // May involve function calls. 
     // 
     // I worry that anything the adds new stack frames 
     // will disrupt the saved state of futureContext 
     // 
     // But without detailed information I can not be sure 
     // if this is an allowed senario. 
     backToFuture = 1; 
     setcontext(&futureContext); 
    } 
} 

उत्तर

4

getcontext ढेर नकल नहीं है, यह केवल रजिस्टरों और संकेत मुखौटा की तरह एक छोटे से संदर्भ डेटा, आदि

(ढेर सूचक सहित) उदासीनता जब आप ढेर यह शीर्ष संदर्भ को अमान्य कर नीचे कूद। भले ही आप कोई फंक्शन कॉल नहीं करेंगे सिग्नल हैंडलर के बारे में सोचें जो वहां निष्पादित कर सकता है। यदि आप दो ढेर के बीच कूदना चाहते हैं तो आपको makecontext की आवश्यकता है।

void func(void) 
{ 
    // Some complex calc 
    if (1) 
    { 
     volatile int neverChange = 1; 
     getcontext(&futureContext); // After returning I want to come back 
            // here to carry on with my work. 
     printf("neverchange = %d\n", neverChange); 
     if (backToFuture == 0) 
     { 
      setcontext(&context); // rewind to get stuff-done 
     } 
    } 
    // Finishe work 
} 

मेरी मशीन पर यह परिणाम:

getcontext has been called 
neverchange = 1 
setcontext has been called 
neverchange = 32767 
+0

आप उपयोग कर अपनी पोस्ट में कोड के सही संस्करण प्रदान कर सकते हैं 'makecontext

मैं चर यह दर्शाता है कि है कि अपने कोड अमान्य है जोड़ा '? सटीक होने के लिए, मैं सिग्नल हैंडलर में पतली हवा से फ़ंक्शन कॉल बनाना चाहता हूं (जिसे हैंडलर रिटर्न के बाद निष्पादित किया जाना चाहिए)। मैं भी इस नए बनाए गए फ़ंक्शन में फेंकने और बाहरी मूल संदर्भ पर प्रयास/पकड़ने के लिए अवांछित (फेंक/पकड़) को सही तरीके से काम करना चाहता हूं। मुझे लगता है कि एक गतिशील फ़ंक्शन कॉल (स्टैक फ्रेम निर्माण) बनाना आवश्यक है। मुझे यकीन नहीं है कि यह setcontext के साथ संभव है या नहीं (ucontel_t में uc_link?)। – Etherealone

+0

मैं इस नव निर्मित फ़ंक्शन कॉल पर मेकॉनटेक्स्ट का उपयोग करने में कामयाब रहा लेकिन सिग्नल_हैंडलर के अंतिम पैरामीटर (ucontext_t) में uc_link सेट करने से नई फ़ंक्शन कॉल निष्पादित करने के बाद पुराने संदर्भ में सही ढंग से वापस नहीं आ जाता है। (पीएस मेरी पिछली टिप्पणी में अवांछित ढेर का उद्देश्य यह है कि मैं एक अपमानजनक ऑपरेशन को साफ करना चाहता हूं जो एक सिग्नल बनाता है जो विनाशकारी नहीं है)। – Etherealone

+0

@Etherealone, मुझे लगता है कि इस टिप्पणी धागे के लिए बहुत जटिल है, लेकिन मुझे एक प्रश्न से लिंक करने में संकोच न करें, क्या आपको एक बनाना चाहिए। – zch