首页 > 代码库 > 第四十一天:Linux内核栈

第四十一天:Linux内核栈

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

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

  技术分享

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

 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);

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

 技术分享

  下面来解释下关键代码:

  第十一行;在内核栈上定义一个整型变量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);
技术分享

container_of宏在内核中应用很广,一定要看懂。

  

  

 

  

 

  

   

   

  

第四十一天:Linux内核栈