2010-09-22 15 views
7

हालांकि इस मंच और अन्य सभी मंचों में इस विषय पर कई बार चर्चा की गई है, फिर भी मुझे संदेह है। कृपया मदद करे।{} जबकि (0) मैक्रो में कैसे काम करता है?

लिनक्स कर्नेल में मैक्रो काम में do{} while(0) कैसे करता है? उदाहरण के लिए,

#define preempt_disable() do { } while (0) 

यह कैसे जगह ले लेना अक्षम करता है?

#define might_resched() do { } while (0) 

यह कैसे पुन: निर्धारित करता है?

इसी प्रकार मैंने म्यूटेक्स ताले और अन्य के लिए मैक्रोज़ को भी देखा है। यह कैसे मदद करता है? मैं समस्या का पालन करने के लिए समझता हूं लेकिन ऊपर दिए गए उदाहरणों के लिए नहीं।

#define foo(x) do { do something } while(0) 

संपादित करें:

क्या rt_mutex_lock के लिए निम्न कोड के बारे में?

/** 
* rt_mutex_lock - lock a rt_mutex 
* 
* @lock: the rt_mutex to be locked 
*/ 
void __sched rt_mutex_lock(struct rt_mutex *lock) 
{ 
     might_sleep(); 
     rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock); 
} 
EXPORT_SYMBOL_GPL(rt_mutex_lock); 


/* 
* debug aware fast/slowpath lock,trylock,unlock 
* 
* The atomic acquire/release ops are compiled away, when either the 
* architecture does not support cmpxchg or when debugging is enabled. 
*/ 

static inline int rt_mutex_fastlock(struct rt_mutex *lock, 
    int state, int detect_deadlock, int (*slowfn)(struct rt_mutex *lock, 
    int state, struct hrtimer_sleeper *timeout, int detect_deadlock)) 
{ 
     if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { 
       rt_mutex_deadlock_account_lock(lock, current); 
       return 0; 
     } else{ 
       return slowfn(lock, state, NULL, detect_deadlock); 
     } 
} 

मैं उलझन में हूँ क्योंकि rt_mutex_deadlock_account_lock कर्नेल में दो स्थानों पर परिभाषित है:

kernel/rtmutex-debug.c में:

void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, 
    struct task_struct *task) 
{ 
    //.... 
} 

kernel/rtmutex.h में:

#define rt_mutex_deadlock_account_lock(m, t) do { } while (0) 

नया कर्नेल 2.6 में। 35.4 i2c ड्राइवर rt_mutex_lock(&adap->bus_lock); हेक्टेयर में mutex_lock() को प्रतिस्थापित किया गया है। तब यह लॉक कैसे होता है?

+0

मुझे लगता है कि यह कार्य कुछ भी करने के लिए फिर से परिभाषित करता है। – mpen

+0

@ मार्क: समझदार लगता है। ravspratapsingh: क्या हमें यह सही मिला है कि दो ऊपरी बयान के लिए, ब्रेसिज़ के बीच वास्तव में कुछ भी नहीं है? या आपने इस तरह कोड को सरल बना दिया है? – chiccodoro

+0

संभावित डुप्लिकेट [जब हम मैक्रो को परिभाषित करते हैं तो (0) का उपयोग क्या होता है?] (Http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we- Define-a-macro) – paxdiablo

उत्तर

5

@ क्रैगेन ने जवाब दिया है कि क्या करना है ... जबकि निर्माण के लिए है - यह मूल रूप से उपयोग करने के लिए एक मैक्रो अधिक सुरक्षित बनाता है।

#define preempt_disable() do { } while (0) 

मैक्रो को परिभाषित किया गया है कुछ भी नहीं कार्य करें:

हालांकि, मैं इसके बारे में? "कैसे करता है यह काम" सवाल का जवाब नहीं लगता। आप कुछ भी क्यों नहीं करना चाहेंगे?

  • कुछ मामलों में आप कुछ करने के लिए प्लेसहोल्डर के रूप में मैक्रो का उपयोग करना चाहते हैं।उदाहरण के लिए, आप एक सिस्टम पर कोड लिख सकते हैं जहां "प्रीempt" कोई मुद्दा नहीं है, लेकिन आप जानते हैं कि कोड को उस सिस्टम में पोर्ट किया जा सकता है जहां "प्रीempt" को कुछ विशेष हैंडलिंग की आवश्यकता होती है। तो आप दूसरी प्रणाली को हर जगह मैक्रो का उपयोग करते हैं (ताकि बाद में हैंडलिंग को सक्षम करना आसान हो), लेकिन पहले सिस्टम के लिए आप उस मैक्रो को रिक्त मैक्रो के रूप में परिभाषित करते हैं।

  • कुछ मामलों में आप अलग-अलग हिस्सों से बने कार्य की तरह चीजें करना चाहते हैं, (उदा। START_TABLE(); TABLE_ENTRY (1); TABLE_ENTRY (2); END_TABLE();)। यह आपकी तालिका का एक अच्छा साफ स्पष्ट कार्यान्वयन बनाता है। लेकिन फिर आप पाते हैं कि आपको वास्तव में END_TABLE() मैक्रो की आवश्यकता नहीं है। क्लाइंट कोड को साफ रखने के लिए, आप मैक्रो परिभाषित छोड़ देते हैं, और बस कुछ भी करने के लिए इसे परिभाषित नहीं करते हैं। इस तरह, आपके सभी टेबलों में एक END_TABLE है और कोड पढ़ने के लिए आसान है।

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

+0

यदि 'do {} जबकि (0) 'कुछ भी नहीं करता है। क्या संकलक कचरा निर्देश उत्पन्न करता है या लूप को अनुकूलित किया जाएगा? – Zingam

+1

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

11

this link देखें जो मैं दे सकता हूं उससे बेहतर स्पष्टीकरण के लिए।

+2

+1 बस एक स्तर का संकेतक पॉप अप करने के लिए, पहले उद्धरण में सवाल का जवाब दिया गया है: (डेव मिलर से) खाली बयान कंपाइलर से चेतावनी देते हैं इसलिए यही कारण है कि आप '# परिभाषित करें {} जबकि (0) '। –

3

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

मुझे लगता है कि इस मामले में उन मैक्रोज़ का उपयोग किया जा रहा है, इसलिए कुछ फ़ंक्शन कॉल कुछ भी संकलित नहीं होते हैं; ऐसा लगता है कि CONFIG_PREEMPT सेट नहीं किया गया था, तो हो सकता है कि कर्नेल के कुछ हिस्सों जो केवल विक्टोरेशन के लिए जरूरी हैं, बिना बस गायब हो जाएं। तो उन loops preempt या reschedule कुछ भी अक्षम नहीं करते हैं; कर्नेल स्रोत में कहीं और एक और परिभाषा (शायद एक वास्तविक कार्य) होगी।

+0

धन्यवाद, मुझे समझ में आया कि यह छूट चीज कैसे काम करती है लेकिन अभी भी म्यूटेक्स लॉक के बारे में उलझन में है। कृपया rt_mutex_lock – iSegFault

+1

के बारे में मेरा उत्तर देखें मुझे लगता है कि म्यूटेक्स लॉक कुछ समान है - एक "असली" कार्यान्वयन और "डमी" है जो कुछ भी नहीं करता है। संभवतः कुछ मामलों में डमी का उपयोग किया जाता है यदि कर्नेल कॉन्फ़िगर किया गया है कि इसकी कोई आवश्यकता नहीं है - शायद यदि CONFIG_SMP सक्षम नहीं है? – Peter

संबंधित मुद्दे