遍历: 这部分代码比较长,不过有些还是比较相似的,所以不用担心,我们来一步一步往下看。 425#define list_entry ( ptr , type , member ) \ 426 container_of ( ptr , type , member ) 427 List_entry()这个宏又牵扯到一个宏container_of(),有必要把这个宏详细分析下,这个宏用途很广,说明其也很重要。 //在头文件include/linux/kernel.h中有此定义。 318#define container_of ( ptr , type , member ) ({ \ 319 const typeof ( (( type *)0)-> member ) * __mptr = ( ptr ); \ 320 ( type *)( (char *) __mptr - offsetof ( type , member ) );}) 他的作用是:通过结构中的某个变量获取结构本身的指针。 typeof()和offsetof(),它们返回的是某个变量的类型和结构中某变量在结构中的偏移量。typeof()是gcc的扩展。 offsetof宏定义在[include/linux/stddef.h]中: #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) offsetof宏的实现非常巧妙,它把0地址转化为TYPE结构的指针,然后获取该结构中MEMBER成员的指针,并将其强制类型转换为 size_t类型。于是,由于结构从0地址开始定义,因此,强制转换后的MEMBER成员地址,实际上就是它在结构中的偏移量,这也显示出了C语言中指针的强大。 看下面的图六可以帮助理解。ptr是指向结构体type类型中的一个成员(member)的指针,这样三个参数我们都知道了,第319行_mptr强制转换成ptr所指向的类型,然后把ptr赋给它。320行_mptr减去member在type中的偏移量(由offsetof(type,member)算出),这样就等于将ptr指针向后移动了offsetof()个偏移量,即就是指针指向了type指向的位置。一般使用时member成员为struct list_head结构(注意这个,这就是这个宏的妙用,在后面的文章中将会举个例子说明它的妙处)。 screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://blogimg.chinaunix.net/blog/upfile2/081012201010.jpg');}" onmousewheel="return imgzoom(this);" alt="" /> 综上述可知list_entry()可以得到一个type类型的结构体。 436#define list_first_entry ( ptr , type , member ) \ 437 list_entry (( ptr )-> next , type , member ) 知道了list_entry()的用法,list_first_entry()就无需多言了吧。 444#define list_for_each ( pos , head ) \ 445 for ( pos = ( head )-> next ; prefetch ( pos -> next ), pos != ( head ); \ 446 pos = pos -> next ) 447 此函数作用:循环访问一个链表。遍历访问是这样进行的:head是链表头,从head->next开始,一直到pos指向最后一个项即就是head->prev为止,函数prefetch()是预先取得下一个链表项,为了加快速度。 458#define __list_for_each ( pos , head ) \ 459 for ( pos = ( head )-> next ; pos != ( head ); pos = pos -> next ) 460 这个宏和list_for_each()类似,不同之处在于,这个没有预取函数prefetch(),一般是短链表才使用这个宏。 461/** 462 * list_for_each_prev - iterate over a list backwards 463 * @pos: the &struct list_head to use as a loop cursor. 464 * @head: the head for your list. 465 */ 466#define list_for_each_prev ( pos , head ) \ 467 for ( pos = ( head )-> prev ; prefetch ( pos -> prev ), pos != ( head ); \ 468 pos = pos -> prev ) 469 此宏和list_for_each()相反,沿着相反的方向(head->prev)遍历,最后是pos指向了head->next。 476#define list_for_each_safe ( pos , n , head ) \ 477 for ( pos = ( head )-> next , n = pos -> next ; pos != ( head ); \ 478 pos = n , n = pos -> next ) 479 这个宏是list_for_each()的“安全版”,它先将pos的下一个即pos->next赋给n,然后pos=n;防止了pos->next在未赋值给pos前被移除造成的链表断裂。 486#define list_for_each_entry ( pos , head , member ) \ 487 for ( pos = list_entry (( head )-> next , typeof (* pos ), member ); \ 488 prefetch ( pos -> member . next ), & pos -> member != ( head ); \ 489 pos = list_entry ( pos -> member . next , typeof (* pos ), member )) 遍历一个给定链表,member为链表项中的成员,为struct head_list型,head为链表头,最后将指向链表的最后一项。 497#define list_for_each_entry_reverse ( pos , head , member ) \ 498 for ( pos = list_entry (( head )-> prev , typeof (* pos ), member ); \ 499 prefetch ( pos -> member . prev ), & pos -> member != ( head ); \ 500 pos = list_entry ( pos -> member . prev , typeof (* pos ), member )) 与list_for_each_entry()类似,只不过是反向遍历而已。 |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-30 13:32 , Processed in 0.153657 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.