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! :)
Sana Linux çekirdeği anlama kitap okumak öneririz. – stdcall
Öneriniz için teşekkür ederiz, bu kitap liste ile ilgili iyi içeriğe sahip .. – goodies