GDB एक निष्पादन को कैसे रोकती है


16

जैसा कि आप जानते हैं, हम डीबीडी जीडीबी का उपयोग कर सकते हैं और डिबगिंग के लिए निष्पादन को रोकने के लिए हमारे कोड पर ब्रेकपॉइंट सेट कर सकते हैं।

मेरा प्रश्न है, GDB एक प्रक्रिया को कैसे रोकती है और आपको i rउदाहरण के लिए रजिस्टरों की सामग्री को देखने देती है । क्या उन रजिस्टर को अन्य OS प्रक्रियाओं द्वारा लगातार उपयोग नहीं किया जा रहा है? वे ओवरराइट कैसे नहीं करते?

क्या यह केवल सामग्री का स्नैपशॉट है और डेटा नहीं है?


2
जब ओएस आपके कार्यक्रम को एक पल के लिए रोक देने और एक अलग चलाने का फैसला करता है तो सभी रजिस्टर कैसे ओवरराइट नहीं होते हैं?
user253751

CppCon 2018: साइमन ब्रांड "How C ++
डीबगर्स

जवाबों:


24

यह वास्तुकला के साथ थोड़ा भिन्न होता है, लेकिन महत्वपूर्ण बिंदु लगभग सार्वभौमिक रूप से लागू होते हैं:

  • इंटरप्ट सर्विसिंग के कारण ISR को चलाने से पहले CPU स्थिति (रजिस्टरों सहित) को मेमोरी में सेव किया जा सकता है, और ISI के बाहर निकलते ही बहाल कर दिया जाता है।

  • यदि कोई रुकावट सेवा दिनचर्या स्मृति स्थान की सामग्री को स्वैप करती है, जहां उन रजिस्टरों को बचाया जाता है, तो यह एक संदर्भ स्विच कर सकता है । प्रत्येक थ्रेड में एक मेमोरी क्षेत्र होता है, जहां थ्रेड न चलने पर उसके रजिस्टरों को सहेजा जाता है।

  • संदर्भ स्विच को एक थ्रेड शेड्यूलर द्वारा नियंत्रित किया जाता है, जो इस बात पर ध्यान देता है कि क्या थ्रेड I / O, सिंक्रोनाइज़ेशन की प्रतीक्षा कर रहा है, उसकी प्राथमिकता क्या है, सिग्नल डिलीवरी, आदि। अक्सर एक सस्पेंड काउंट होता है जो कि वास्तव में है।

  • डिबगर सस्पेंड काउंट को बढ़ा सकता है, जो गारंटी देता है कि थ्रेड योग्य नहीं है। फिर यह रजिस्टरों की धागे की सहेजी गई प्रतिलिपि का निरीक्षण (और परिवर्तन) कर सकता है।


14

@BenVoigt द्वारा महान जानकारी के अलावा, मुझे कुछ अतिरिक्त बनाने की अनुमति दें:

एक ब्रेकपॉइंट को डीबगर द्वारा मशीन कोड मान (एक निर्देश या एक निर्देश का हिस्सा) की प्रक्रिया में सेट किया जाता है, जो कोड में उस स्थान पर एक विशेष जाल निर्देश के साथ डिबग किया जा रहा है जो वांछित (स्रोत) लाइन से मेल खाता है। यह विशेष रूप से ट्रैप निर्देश एक ब्रेकपॉइंट के रूप में उपयोग के लिए है - डिबगर यह जानता है और इसलिए ऑपरेटिंग सिस्टम करता है।

जब प्रक्रिया / थ्रेड डीबग किया जा रहा है, तो ट्रैप निर्देश हिट करता है, जो @Ben प्रक्रिया को ट्रिगर करता है, जिसमें वर्णन किया जा रहा है, जिसमें एक संदर्भ स्वैप का आधा हिस्सा शामिल है जो कि वर्तमान में चल रहे थ्रेड को निलंबित कर देता है (जिसमें इसकी CPU स्थिति को मेमोरी में सहेजना शामिल है) संभावित बाद में विघटन के लिए। चूंकि यह जाल एक ब्रेकपॉइंट जाल है, इसलिए ऑपरेटिंग सिस्टम डिबग किए जा रहे प्रक्रिया को संभवत: @Ben वर्णित करता है, और सूचित करता है और अंततः डिबगर को फिर से शुरू करता है।

डिबगर सिस्टम कॉल का उपयोग करता है, फिर, निलंबित प्रक्रिया / थ्रेड के डीबग किए जाने की सहेजी स्थिति तक पहुँचने के लिए।

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

वास्तविक विवरण अधिक जटिल हो सकता है, जिसमें लंबे समय तक चलने वाले ब्रेकपॉइंट को हिट रखने का मतलब है कि वास्तविक कोड के लिए ब्रेकपॉइंट जाल को स्वैप करने जैसा कुछ करना ताकि लाइन चल सके, और फिर ब्रेकपॉइंट को फिर से स्वैप कर सके ...

क्या अन्य ओएस प्रक्रियाओं द्वारा लगातार उपयोग किए जा रहे रजिस्टर नहीं हैं? वे ओवरराइट कैसे नहीं करते?

जैसा कि @Ben वर्णन करता है, पहले से मौजूद थ्रेड सस्पेंड / रिज्यूम फ़ीचर ( मल्टीटास्किंग का संदर्भ स्विचिंग / स्वैपिंग ) का उपयोग करते हुए, जो प्रोसेसर को कई प्रक्रियाओं / थ्रेड्स को समय स्लाइसिंग का उपयोग करके साझा करने की अनुमति देता है।

क्या यह केवल सामग्री का स्नैपशॉट है और डेटा नहीं है?

यह दोनों है। चूंकि थ्रेडपॉइंट को हिट करने वाले थ्रेड को निलंबित कर दिया गया है, यह निलंबन के समय लाइव डेटा (सीपीयू रजिस्टर, आदि ..) का एक स्नैपशॉट है और प्रोसेसर में पुनर्स्थापित करने के लिए सीपीयू रजिस्टर के आधिकारिक मास्टर को थ्रेड को फिर से शुरू करना चाहिए। । यदि आप डिबगर के उपयोगकर्ता इंटरफ़ेस को पढ़ने और / या सीपीयू रजिस्टर (डिबग की जा रही प्रक्रिया) को बदलने के लिए उपयोग करते हैं, तो यह सिस्टम कॉल का उपयोग करके इस स्नैपशॉट / मास्टर को पढ़ेगा और / या बदल देगा।


1
खैर, अधिकांश प्रोसेसर आर्किटेक्चर डिबग ट्रैप का समर्थन करते हैं जो उदाहरण के लिए ट्रिगर करते हैं जब आईपी (इंस्ट्रक्शन पॉइंटर) एक ब्रेकपॉइंट रजिस्टर में संग्रहीत पते के बराबर होता है, जिससे कोड को फिर से लिखने की आवश्यकता होती है। (आईपी के अलावा अन्य रजिस्टरों का मिलान करके, आप डेटा ब्रेकप्वाइंट प्राप्त कर सकते हैं, और हर निर्देश के बाद फंसकर, आप सिंगल स्टेपिंग प्राप्त कर सकते हैं) आपने जो वर्णित किया है वह भी निश्चित रूप से संभव है, जब तक कि कोड एक रीडायरी मेमोरी में नहीं है।
बेन वोइग्ट

पुन: "यदि आप सीपीयू रजिस्टरों में परिवर्तन करते हैं ..." अंतिम पैराग्राफ में, मुझे लगता है कि आपका मतलब है "यदि आप सीयूपी रजिस्टरों की सहेजी गई प्रतिलिपि को बदलते हैं ..." तब जब ओएस प्रक्रिया को फिर से शुरू करता है, तो बदल दिया गया डेटा वापस लिखा जाता है वास्तविक रजिस्टरों के लिए।
जेम्सकफ

@jamesqf, हाँ, thx!
एरिक Eidt

@BenVoigt, सहमत। हालांकि डिबगर्स असीमित संख्या में ब्रेकप्वाइंट को संभाल सकते हैं, हार्डवेयर शून्य या कुछ को हैंडल कर सकता है, इसलिए डिबगर को कुछ तस्करी करनी पड़ती है।
एरिक Eidt

@jamesqf: यह बताना कि एक प्रति के रूप में एक भ्रामक है। यह थ्रेड स्थिति के लिए आधिकारिक संग्रहण है जबकि थ्रेड नहीं चल रहा है।
बेन वोइगट

5

कड़े शब्दों में, कम से कम ज्यादातर विशिष्ट मामलों में, जीडीबी ही निष्पादन को रोक नहीं देता है। बल्कि, जीडीबी ओएस से पूछता है, और ओएस निष्पादन को रोक देता है।

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

ऐसा करने के लिए, ओएस में आमतौर पर मशीन की वर्तमान स्थिति को बचाने के लिए प्रत्येक थ्रेड के लिए अलग से मेमोरी सेट होता है। जब किसी थ्रेड को रोकने की आवश्यकता होती है, तो मशीन की वर्तमान स्थिति उस क्षेत्र में सहेजी जाती है। जब इसे एक थ्रेड को फिर से शुरू करने की आवश्यकता होती है, तो मशीन का राज्य उस क्षेत्र से बहाल हो जाता है।

जब डीबगर को थ्रेड पॉज़ करने की आवश्यकता होती है, तो इसमें OS पॉज़ होता है जो कि अन्य कारणों से ठीक उसी तरह से थ्रेड होता है। फिर, रुके हुए धागे की स्थिति को पढ़ने के लिए, डिबगर थ्रेड के सहेजे गए स्थिति को देखता है। यदि आप राज्य को संशोधित करते हैं, तो डिबगर सहेजे गए स्थिति में लिखता है, जब थ्रेड फिर से शुरू होने पर प्रभावी होता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.