linux/arch/x86/include/asm/switch_to.h
में, वहाँ मैक्रो switch_to
की परिभाषा, कुंजी लाइनों जो वास्तविक धागा स्विच चमत्कार इस तरह पढ़ कर (लिनक्स 4.7 तक जब यह बदल):स्विच_ओ को सीधे जेएमपी के बजाय ईआईपी बदलने के लिए पुश + जेएमपी + रीट का उपयोग क्यों करता है?
asm volatile("pushfl\n\t" /* save flags */ \
pushl %%ebp\n\t" /* save EBP */ \
"movl %%esp,%[prev_sp]\n\t" /* save ESP */ \
"movl %[next_sp],%%esp\n\t" /* restore ESP */ \
"movl $1f,%[prev_ip]\n\t" /* save EIP */ \
"pushl %[next_ip]\n\t" /* restore EIP */ \
__switch_canary \
"jmp __switch_to\n" /* regparm call */ \
"1:\t" \
"popl %%ebp\n\t" /* restore EBP */ \
"popfl\n" /* restore flags */ \
नामित ऑपरेंड [prev_sp] "=m" (prev->thread.sp)
तरह स्मृति की कमी है । __switch_canary
जब तक CONFIG_CC_STACKPROTECTOR
परिभाषित किया गया है कुछ भी नहीं करने के लिए परिभाषित किया गया है (तो यह एक लोड और %ebx
का उपयोग कर दुकान है)।
मैं समझता हूँ कि यह कैसे काम करता है, कर्नेल ढेर सूचक बैकअप की तरह/बहाल, और कैसे push next->eip
और jmp __switch_to
समारोह के अंत में, जो वास्तव में एक "नकली" कॉल अनुदेश एक असली ret
के साथ मिलान किया है पर एक ret
अनुदेश के साथ निर्देश, और प्रभावी ढंग से अगले धागे के वापसी बिंदु next->eip
बनाते हैं।
क्या मुझे समझ नहीं आता है, क्यों हैक? क्यों सिर्फ call __switch_to
नहीं है, तो यह बाद ret
, jmp
next->eip
को, जो और अधिक स्वच्छ और पाठक के अनुकूल है।
लेकिन यह प्रभावी ढंग से वापसी-भविष्यवाणी ढेर मार नहीं होगा? – harold
हां - लेकिन लक्ष्य पंजीकृत करने के लिए 'jmp' भी करता है, जैसा कि आप _never_' switch_to() 'पर वापस लौटना चाहते हैं, वास्तव में (अगले संदर्भ स्विच तक)। जहां तक दोनों के बीच कोई अंतर नहीं है। –
@harold: अच्छा बिंदु; रिटर्न-एड्रेस पूर्वानुमानकर्ता स्टैक की वर्तमान सामग्री 'context_switch()' ([कर्नेल/शेड/कोर.c' में] से वापसी के संदर्भ संदर्भ के बाद मूल्यवान है (http://elixir.free-electrons.com /linux/v4.6/source/kernel/sched/core.c#L2752)), और हो सकता है कि कुछ स्तर शेड्यूलर में कॉल स्टैक का बैक अप लें (जब तक उनके बैकट्रैस अलग नहीं हो जाते)।लेकिन यह केवल तभी सच है जब '% [next_ip]' हमेशा/आमतौर पर switch_to के अंदर होता है; यह उस तरह से 'prev_ip' सेट करता है, लेकिन हो सकता है कि यह सबसे आम मूल्य नहीं है (कर्नेल प्री-एम्प्शन शायद इसे कहीं और छोड़ सकता है?) –