转载

第四十一天:Linux内核栈

linux3.5内核中为所有进程(包括内核进程和用户进程)分配8k或4k的内核栈(可以在内核编译的时候选择),在模块代码中分配的栈内存就是在内核栈中,写模块代码如果要在堆中分配内存,则要使用kmalloc或vmalloc来分配,这是后话。

内核栈的栈底存放这thread_info, 通过获取内核栈,以得到thread_info的信息,thread_info里面有一个指向task_struct (进程描述符, 里面放着进程的各种信息)的指针, 通过这个指针, 就可以获取进程的各种信息了。

第四十一天:Linux内核栈

先编写获取当前进程名的程序,来更好的了解内核栈。

 1 #include <linux/init.h>  2 #include <linux/module.h>  3 #include <asm/thread_info.h>  4 #include <linux/sched.h>  5   6 MODULE_LICENSE("GPL");  7 MODULE_AUTHOR("BUNFLY");  8   9 int test_init() 10 { 11         int i = 0; 12         struct thread_info *p = NULL; 13         p = (struct thread_info *)((unsigned long)&i & ~0x1fff); 14         struct task_struct *t = p->task; 15         printk("task name is %s/n", t->comm); 16  17         return 0; 18 } 19  20 void test_exit() 21 { 22         printk("bye bye/n"); 23 } 24  25 module_init(test_init); 26 module_exit(test_exit);

编译成模块,在开发板运行结果如下;

第四十一天:Linux内核栈

下面来解释下关键代码:

第十一行;在内核栈上定义一个整型变量i 

第十二行,定义指向thread_info结构体指针p

第十三行:根据上图所示 ,已知 thread_info结构体 在内核栈的栈底,整型变量i在栈上,可以获得i的地址,内核栈的大小是8k。求 thread_info结构体 的地址。方法就是第十三行代码:将i强制转换成unsigned long 型,再将后面13位置零,再强转为 thread_info结构体 指针。要理解为什么这样并不难。联想下内存的段页式存储,内存地址中前面为基地址,后面是偏移量,内核栈的大小是8k。说明是以8k大小作为偏移量的。后13位置零就是求出基地址,而 thread_info结构体 是在栈底的,也就是说,基地址就是 thread_info结构体 的地址。

第十四行定义内存描述符task_struct结构体指针t,并保存 thread_info结构体 中task的地址。

第十五行输出进程名称。

系统中所有的进程连成一个双向循环链表,现在我们就通过已经找到进程描述符来输出系统中所有的进程名。

 1 #include <linux/init.h>  2 #include <linux/module.h>  3 #include <asm/thread_info.h>  4 #include <linux/sched.h>  5   6 MODULE_LICENSE("GPL");  7 MODULE_AUTHOR("BUNFLY");  8   9 int test_init() 10 { 11     //printk("name is %s/n", current->comm); 12     struct thread_info *p = NULL; 13     p = (struct thread_info *)((unsigned long)&p  & ~(8192 - 1)); 14      15     struct task_struct *head = p->task; 16     struct task_struct *tmp = head; 17     do{ 18         printk("name is %s/n", tmp->comm); 19         tmp = container_of(tmp->tasks.next, struct task_struct, tasks); 20     }while(tmp != head); 21  22  23     return 0; 24 } 25  26 void test_exit() 27 { 28     printk("bye bye/n"); 29 } 30  31 module_init(test_init); 32 module_exit(test_exit);
第四十一天:Linux内核栈

container_of宏在内核中应用很广,一定要看懂。
正文到此结束
Loading...