2013-04-26 16 views
16

List_for_each_entry ve ... entry_safe döngüsünün Linux'ta çalışmasını açıklayabilir mi? Tüm bu parametrelerin rolü nelerdir ve bunlar listesinde geçiş için nasıl kullanıldığını List_for_each_entry ve list_for_each_entry_safe açıklamasını belirtin

list_for_each_entry(type *cursor, struct list_head *list, member)

gibi

list_for_each_entry_safe(type *cursor, type *next, struct list_head *list,member)

olduğunu. PEŞİN

Teşekkür

+1

Sana Linux çekirdeği anlama kitap okumak öneririz. – stdcall

+0

Öneriniz için teşekkür ederiz, bu kitap liste ile ilgili iyi içeriğe sahip .. – goodies

cevap

12

DÜZENLEME: üzgün, geç, ben yazım hatalarını bir sürü yaptık olmalıdır.

Onlar saf eğlencelidir! :) Farkı, listeyi yinelemek ve list_for_each_entry_safe (bazı ekstra CPU talimatları pahasına pahasına değil) bir şey silerseniz, list_for_each_entry kopacaktır. list.h. bir singingly bağlantılı liste uygulaması olmasına rağmen

çekirdeği, (Anladığına 'Küstah) doubly bağlı listeleri yerleşmiş durumda Listeniz adildir: Aynı yapı listesinin "kafa" in yanı sıra her düğüm her ikisi için kullanılır

struct list_head { 
    struct list_head *next; 
    struct list_head *prev; 
}; 

Not söyledi. Liste boş olduğunda, kafanın next ve prev üyeleri sadece kendi başlarına işaret eder. Böylece, liste yineleme kafan next üyesi ile başlayan ve prev aynı adresi (durdurmak) olmadığı sürece, bu düğüm çağıran sadece bir süreçtir. Aksi takdirde, for gövdesini çağırır ve gerçek yapınıza bir işaretçi almak ve onunla oynamak için container_of() makrosunu kullanabilirsiniz. Ardından, for'un 3. alanında, sadece bir sonraki next'a geçelim.

DÜZENLEME: whoop, özür dilerim, parametrelerin açıklamasını istediniz. Şey, eğer birilerinin sözünü almaktan çok ben olsaydım direkt olarak kontrol ederim. Bunlar için, en azından bağlantılı liste kitaplığı için mevcut olan Kernel API docs kendileri öneririm. Kırmızı-siyah ağaç kütüphanesi için onları da ekleyeceğimiz bir yama elde etmeye çalışıyorum, ama bir şeyler almak oldukça bir süreç olabilir. Notun Ayrıca

:

struct list_head my_actual_list; 
struct my_struct { 
    struct list_head node; 
    /* some other members */ 
}; 

/* in a function body somewhere... */ 
struct list_head *i; 
list_for_each(i, &my_actual_list) { 
    struct my_struct *obj = list_entry(i, struct my_struct, node); 
    // do something with obj 
} 

list_entry cevap yüzden, container_of

DÜZENLEME 2.

OK için sadece bir takma: İşte http://kernelnewbies.org/FAQ/LinkedLists

kısa bir örnek Yorumlarınızdaki sorunuza, cevabımı genişleteceğim. C++ STL konteynırları, C dizileri, vb. Ile karşılaştırıldığında birkaç garip şeyi olduğu için, bu kavrayışı kavramanın zorluğunu takdir edebilirim, ama deyimlere alışmaya başladığınızda, oldukça doğal görünecektir. Yine de gelecekte bu yapıların tanımına bakmaya başlamanızı, & makrolarını kendiniz çalıştırmanızı ve bir anlayışı bir araya getirmeye çalışmanızı, sonra da soruları sormanızı rica ediyorum.

Yani ilk kapalı, listenizdeki her düğüm tipi struct list_head üyesi ve kendini tip struct list_head taşımaktadır listesini içeren bir yapı olduğunu. Böylelikle, kap ve kimin bu davada yer aldığı, basitçe nasıl kullanıldığına bağlıdır, ancak tipik olarak, bu üyelerin verildiği isimlerde ifade edilecektir. Yineleyicinin türü struct list_head *'dur. İşte bir örnek ve onların dengi koduyla Normal fonksiyon & makro çağrıları değiştiririz:

struct my_container { 
    struct list_head list; 
    int some_member; 
    /* etc. */ 
}; 

struct my_obj { 
    struct list_head node; 
    int some_member; 
    /* etc. */ 
}; 

void func() { 
    struct my_container container; 
    struct my_obj obj1, obj2; 
    struct list_head *i; 

    /* INIT_LIST_HEAD(&container.list); */ 
    container.list.next = &container.list; 
    container.list.prev = &container.list; 

    /* list_add_tail(&obj1.node); */ 
    container.list.prev = &obj1.node; 
    obj1.node.next = &container.list; 
    obj1.node.prev = &container.list; 
    container.list.next = &obj1.node; 

    /* list_add_tail(&obj2.node); */ 
    container.list.prev = &obj2.node; 
    obj2.node.next = &container.list; 
    obj2.node.prev = &obj1.node; 
    obj1.node.next = &obj2.node; 

    /* list_for_each(i, &container.list) { */ 
    for (i = container.list.next; i != &container.list; i = i->next) { 
     struct my_obj *obj = list_entry(i, struct my_obj, node); 
     /* do stuff */ 
    } 

} 

Now go read! :)

+0

Seni anlıyorum ama onların nasıl ve hangi iteratörün nasıl kontrol edeceğini bilmek istiyorum .. Örn. (int i = 0; i <= 5; i ++) ** böylelikle, bu yineleyicinin bir sonraki öğeyi nasıl kontrol edeceğini, bir sonraki öğeyi nasıl kontrol edeceğini .. – goodies

+1

Ah evet, değişken adını kullandığımı fark edeceksiniz 'Ben, çünkü yineleyicimi arıyorum. Bazı insanlar, 'pos' değişken adını kullanırlar, çünkü listedeki "konum" dur, ancak "yineleyici" kuralına uymayı tercih ederim. Bu uzun, bu yüzden cevabımı genişleteceğim. –

İlgili konular