欣赏linux中的二级指针

__get_vm_area_node()中新线性区插入vmlist,代码片段

197 for (p = c&vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
198 if ((unsigned long)tmp->addr < addr) {
199 if((unsigned long)tmp->addr + tmp->size >= addr)
200 addr = ALIGN(tmp->size +
201 (unsigned long)tmp->addr, align);//落在区的中间了,那么移到区的下边界
202 continue;
203 }
204 if ((size + addr) < addr)//超出了
205 goto out;
206 if (size + addr <= (unsigned long)tmp->addr)//这里找到了未用的区间
207 goto found;
208 addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);//否则,addr指向区间的下边界
209 if (addr > end - size)//end=VMALLOC_END
210 goto out;
211 }
212
213 found:
214 area->next = *p;//area->next=*p
215 *p = area;
216
217 area->flags = flags;
218 area->addr = (void *)addr;
219 area->size = size;
220 area->pages = NULL;
221 area->nr_pages = 0;//还没有映射,所以...
222 area->phys_addr = 0;//还没有映射,所以...
223 write_unlock(&vmlist_lock);

这里,理解area插入的关键是理解:
问题的关键是
p = &tmp->next,
*p =area;
p实际上存放的是tmp->next的地址。也就是说p代表的就是tmp->next。
这样,当到了下一个循环后,p存放的就是上一个vmlist的next指针了,因为tmp已经通过tmp=*p,漂移到下一个节点了。于是:
214 area->next = *p;
就把tmp后面的链表链到area节点后面了。(这个tmp还是上一次循环的tmp)
215 *p = area;
就是tmp->next=area了。(这个tmp也是上一次循环的tmp)
两行代码,把一个数据插入到链表中了,非常简洁!

评论

此博客中的热门博文

Linux/ARM Page Table Entry 属性设置分析

提交了30次才AC ---【附】POJ 2488解题报告

笔记