欢迎访问小站,阅读原文http://www.yandong.org/archives/495
list_head是linux
kernel中非常重要的一个结构体,是双向链表的数据结构体,为了减少浪费,众多链表都是用list_head以及其相关原语操作,比如所有的进程是靠它串联在一起的,所有的inode也靠它串联在一起等等。
struct list_head { struct list_head *next, *prev; }
特别注意的是,list_head中的指针存放的是另一个list_head的地址,而不是含有list_head结构的整个数据结构的地址,如下图。
1. list_entry: 与container_of功能相同; /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) \ container_of(ptr, type, member) 2. list_for_each:向后(next)遍历head所指链表每个节点 /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) 3. list_for_each_prev:向前(prev)遍历head所指链表每个节点 /** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each_prev(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev) 4. list_for_each_entry: /** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member))
(1)遍历所有进程
Struct task_struct *p; for_each_process(p) { printk(KERN_ERR "pid is %d\n", p->pid); printk(KERN_ERR "comm is %s\n", p->comm); }
其中for_each_process(p)的定义如下,
#define for_each_process(p) \ for(p=&init_task; ( p=list_entry( (p)->tasks.next, \ struct task_struct, tasks ) )!=&init_task; )
init_task是全局符号,代表init进程(即1号进程),在system.map文件中可以看到init_task进程的地址
tasks 是进程结构体task_struct中的元素,定义为 struct
list_head tasks
(2)遍历得到进程的所有子进程
static int my_child(struct task_struct * p,int num) { struct task_struct * task; struct list_head *list; list_for_each(list,&p->children) { task = list_entry(list,struct task_struct,sibling); printk(KERN_ERR "--%s[%d %x]", task->comm,task->pid, task); } return 1; }
(3)根据进程中的inode遍历系统中所有的inode
struct inode * inode_ptr=p->fs->pwd.dentry->d_inode; for(;( inode_ptr=list_entry(inode_ptr->i_list.next, \ struct inode, i_list) )!= \ (p->fs->pwd.dentry->d_inode);) { ... }