日志标签 ‘list’

遍历进程链表

2010年10月25日

我们知道,一个进程是由进程控制块(PCB),代码段和数据段组成的;并且,OS通常是通过PCB来感知一个进程的存在。其实PCB就是操作系统对每个进程的代码描述。linux内核中使用task_struct结构来描述一个PCB(具体可以在linux/kernel/sched.c查看源码);多个进程则常常使用双链表等来进行组织。比如可运行状态的进程组成可运行队列,等待状态的进程组成等待队列等。

本文将使用前文中所分析的list_head结构来遍历内核中的进程链表。task_struct结构中使用多个字段来详细的描述一个进程。本文中所属的遍历函数只打印一些常用的信息,即进程名称,进程的pid。

我们利用list.h中的下述遍历宏对整个进程链表进行遍历:

420#define list_for_each_entry(pos, head, member)                          \
421        for (pos = list_entry((head)->next, typeof(*pos), member);      \
422             prefetch(pos->member.next), &pos->member != (head);        \
423             pos = list_entry(pos->member.next, typeof(*pos), member))

先简单了解一下这个宏的使用方法。由于list_head结构中没有数据字段,所以它经常被嵌套在其他的结构体当中。pos指向包含list_struct结构的结构体;head为list_head类型的指针,我们可以使用链表中任意一个结点的指针;member即为list_head类型的变量名。

对应到我们下面的程序,pos为指向task_struct类型的指针,我们通过遍历宏即得到每个进程对应的task_struct类型的指针;我们将current_head赋予遍历宏中的第二个参数,current是一个宏,即为系统内正在运行的进程;由于list_struct结构在task_struct结构中的变量明为tasks,因此我们将tasks传递给便利宏的第三个参数。

#include< linux/init.h >
#include< linux/module.h >
#include< linux/sched.h >
#include< linux/sem.h >
#include< linux/list.h >

static int __init  traverse_init(void)
{
      struct task_struct *pos;
      struct list_head *current_head;
      int count=0;

      printk("Traversal module is working..\n");
      current_head=&(current->tasks);
      list_for_each_entry(pos,current_head,tasks)
      {
             count++;
             printk("[process %d]: %s\'s pid is %d\n",count,pos->comm,pos->pid);
      }
      printk(KERN_ALERT"The number of process is:%d\n",count);
      return 0;
}

了解了便利宏的使用方法,那么理解上述代码就简单的多了。关于便利宏的代码详解可参考这里的文章。

加载函数要做的工作就是这些,那么卸载函数的功能就相对于简单多了。

static void __exit traverse_exit(void)
{
  printk("hello world exit\n");
}

OK,编译,插入内核,再查看内核日志文件吧!

list.h的简单应用

2010年8月18日

既然我们分析了list.h,那么就要学以致用,因为通过具体的例子我们才能真实感受到双链表的用法。本文首先为你呈现一个最基本的双链表使用方法,然后在引用另外两个例子,大家可以去亲自试试。

1.简单的学生管理系统

这里学生管理系统只是个基本模型:用户输入数据,然后通过输出重定向到stuInfo.txt文件当中。先看学生信息数据结构:

struct postinfo
{
	char id[20];
	char name[20];
	char sex[10];
	char addr[50];
	char email[20];
	struct list_head list;
};

正如我们前面所说的那样,整个双链表是通过struct list_head结构链接起来的,这样我们每次对某个结点的操作,都是先获得list字段的地址,进而通过list_entry宏获得当前结点的地址。

首先,创建头指针。注意我这里说的是头指针,并不是头结点,因此你应该可以理解为什么下面会首先创建一个struct list_head类型的变量,而不是struct postinfo类型的变量。

	struct list_head head;
	INIT_LIST_HEAD(&head);

创建好头指针,我们接下来就去增加学生信息。每次都先生成一个struct postinfo类型的变量tmp,再将每次要增加的信息都暂时保存在此变量中,接着就利用上次我们所说的增加函数:

list_add_tail(&(tmp->list),head);

注意这里我们使用的是&(tmp->list),正如我们一开始所说的每次对结点的操作实际上都是通过list字段去完成的。

添加完毕后,如何去打印数据?使用我们的遍历宏。pos只是一个struct list_head类型的指针,这个宏会首先使得pos指向head->next,即list链表的第一个结点(而非第一个学生信息结点)。每次移动链表后,通过pos获得当前结点的地址,那么就可以获得其他数据字段的地址了。

	list_for_each(pos,head)
	{
		pinfo=list_entry(pos,struct postinfo,list);
		printf("%s %s %s %s %s\n",pinfo->id,pinfo->name,pinfo->sex,pinfo->addr,pinfo->email);
        }

这个演示程序关键部分就是这样,其他地方只要你有C语言基础,就可以完成的。

2.遍历进程

具体过程请点击这里

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key