第四十一天: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宏在内核中应用很广,一定要看懂。

  

  

  

  

   

   

  

时间: 2024-10-12 15:49:08

第四十一天:Linux内核栈的相关文章

浅谈linux内核栈(基于3.16-rc4)

在3.16-rc4内核源码中,内核给每个进程分配的内核栈大小为8KB.这个内核栈被称为异常栈,在进程的内核空间运行时或者执行异常处理程序时,使用的都是异常栈,看下异常栈的代码(include/linux/sched.h): 1 union thread_union { 2 struct thread_info thread_info; 3 unsigned long stack[THREAD_SIZE/sizeof(long)]; 4 }; THREAD_SIZE值为8KB,因此内核为进程的异常

linux内核栈用户栈切换【转】

转自:http://www.kerneltravel.net/kernel-book/%E7%AC%AC%E5%9B%9B%E7%AB%A0%20%E8%BF%9B%E7%A8%8B%E6%8F%8F%E8%BF%B0/4.4.1.htm 4.4.1进程内核栈 每个进程都有自己的内核栈.当进程从用户态进入内核态时,CPU就自动地设置该进程的内核栈,也就是说,CPU从任务状态段TSS中装入内核栈指针esp(参见下一章的进程切换一节). X86内核栈的分布如图4.2所示:              

Linux0.11内核剖析–内核体系结构 &#169;Fanwu

Linux0.11内核剖析–内核体系结构 ©Fanwu <Linux内核完全注释>下载:http://files.cnblogs.com/files/HanBlogs/linux-kernel.pdf(进入pdf后要点击右下角保存喔^_^) 一个完整可用的操作系统主要由 4 部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如下图所示: 用户应用程序是指那些字处理程序. Internet 浏览器程序或用户自行编制的各种应用程序: 操作系统服务程序是指那些向用户所提供的服务被看作是操作系

centos linux安全和调优 第四十一节课

centos  linux安全和调优    第四十一节课 上半节课 下半节课 f

Linux内核中的中断栈与内核栈的补充说明【转】

转自:http://blog.chinaunix.net/uid-12461657-id-3487463.html 原文地址:Linux内核中的中断栈与内核栈的补充说明 作者:MagicBoy2010 中断栈与内核栈的话题更多地属于内核的范畴,所以在<深入Linux设备驱动程序内核机制>第5章“中断处理”当中,基本上没怎么涉及到上述内容,只是在5.4节有些许的文字讨论中断栈在中断嵌套情形下可能的溢出问题. 本贴在这个基础上对内核栈与中断栈的话题做些补充,讨论基于x86 32位系统,因为64位系

Linux中的栈:用户态栈/内核栈/中断栈

http://blog.chinaunix.net/uid-14528823-id-4136760.html Linux中有多种栈,很容易弄晕,简单说明一下: 1.用户态栈:在进程用户态地址空间底部,跟平时我们简单和理解的一样,就是虚拟地址空间中的一段,不多说~ 2.内核栈:     跟用户态栈是独立的,在用户态和内核态切换时,需要进行切换.     默认8k,可以通过内核配置项修改     跟thread_info结构放在一起,公用一个union:thread_union, 点击(此处)折叠或

Linux源码解析-内核栈与thread_info结构详解

1.什么是进程的内核栈? 在内核态(比如应用进程执行系统调用)时,进程运行需要自己的堆栈信息(不是原用户空间中的栈),而是使用内核空间中的栈,这个栈就是进程的内核栈 2.进程的内核栈在计算机中是如何描述的? linux中进程使用task_struct数据结构描述,其中有一个stack指针 struct task_struct { // ... void *stack; // 指向内核栈的指针 // ... }; task_struct数据结构中的stack成员指向thread_union结构(L

Linux操作系统结构、IO调度器在内核栈中的位置图

1.典型的Linux操作系统结构 2.IO调度器在内核栈中所处的位置 原文地址:https://blog.51cto.com/10627336/2356793

Linux进程管理与调度-之-目录导航【转】

转自:http://blog.csdn.net/gatieme/article/details/51456569 版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatieme 目录(?)[-] 项目链接 进程的描述 进程的创建 进程的加载与运行 进程的退出 进程的调度 调度普通进程-完全公平调度器CFS 日期 内核版本 架构 作者 GitHub CSDN 2016-07-21 Linux-4.6 X86 & arm gatieme