2012-02-09 13 views
11

मैं सीख रहा हूं कि list.h से कर्नेल लिंक्ड-सूची API का उपयोग कैसे करें।कर्नेल लिंक्ड सूची में नोड्स को हटाने के लिए हमें list_for_each_safe() की आवश्यकता क्यों है?

मुझे पता चला कि list_for_each() का उपयोग करने के बजाय list_del() के साथ नोड्स को हटाते समय मुझे list_for_each_safe() का उपयोग करने की आवश्यकता है।

list_for_each_safe() के लिए कोड:

#define list_for_each_safe(pos, n, head) \ 
    for (pos = (head)->next, n = pos->next; pos != (head); \ 
     pos = n, n = pos->next) 

list_for_each() के लिए कोड:

for (pos = (head)->next; pos != (head); pos = pos->next) 

मैं नोटिस वे दोनों को छोड़कर _safe संस्करण एक अतिरिक्त तर्क लेता है कि बहुत समान 'अस्थायी भंडारण' के रूप में इस्तेमाल किया जाएगा (यहां बताया गया है, list.h)।

मैं समझता हूं कि फ़ंक्शन को लागू करने के लिए, _safe संस्करण को हटाने के लिए सामान्य संस्करण को हटाने के लिए, लेकिन मुझे उत्सुकता है कि अतिरिक्त तर्क ने इसे 'सुरक्षित' कैसे बनाया?

, निम्नलिखित पर विचार करें, जहां मैं list_for_each_safe() का उपयोग कर एक लिंक्ड सूची में प्रत्येक नोड को हटा रहा हूं:

struct kool_list{ 
    int to; 
    struct list_head list; 
    int from; 
    }; 

struct kool_list *tmp; 
struct list_head *pos, *q; 
struct kool_list mylist; 

list_for_each_safe(pos, q, &mylist.list){ 
     tmp= list_entry(pos, struct kool_list, list); 
     printf("freeing item to= %d from= %d\n", tmp->to, tmp->from); 
     list_del(pos); 
     free(tmp); 
    } 

कैसे को हटाने में q मदद दे रही है?

किसी भी मदद के लिए धन्यवाद!

+0

मैं, यह मिल गया कभी नहीं सोचा था कि यह इस सीधे आगे है, धन्यवाद ! –

+0

q को बेहतर तरीके से नामित किया जाना चाहिए .. pos_next जैसे कुछ। –

उत्तर

20

आवश्यक है ऐसा इसलिए है क्योंकि list_del आंतरिक रूप से मूल्य को संशोधित करता है pos फ़ील्ड। आपके उदाहरण में लूप बॉडी pos पर कब्जा कर लिया गया स्मृति भी मुक्त करता है। मान लीजिए कि आपको लूप से असुरक्षित संस्करण का प्रयोग करेंगे: pos = pos->next:

for (pos = (head)->next; pos != (head); pos = pos->next) 

पाश शरीर pos सूचक वेतन वृद्धि अभिव्यक्ति तोड़ने अमान्य हो जाता है को क्रियान्वित करने के बाद।

के रूप में विपरीत, सुरक्षित foreach pos->next का मूल्य एक अस्थायी चर में पूर्व की बचत होती है और उसके बाद के बजाय pos अपसंदर्भन के उत्तरार्द्ध को दर्शाता है:

for (pos = (head)->next, n = pos->next; pos != (head); \ 
    pos = n, n = pos->next) 
2
pos = start; 
del(pos); 
pos = pos->next; 

रूप

pos = start; 
n = pos->next; 
del(pos); 
pos = n; 

अगर डेल() नि: शुल्क है() और memset() करने का विरोध किया, pos-> अगले अपरिभाषित है

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