linux 为什么mm_struct->start_stack和vm_area_struct->start不指向同一个地址?

mitkmikd  于 2023-02-03  发布在  Linux
关注(0)|答案(2)|浏览(124)

就我对Linux内核内存管理的理解,每个进程都有一个mm_struct结构负责地址空间,其中一个重要的内存区域是stack,这应该用vm_area_struct内存区域来标识,mm_struct本身有一个指针mm_struct-〉stack_start,是stack的地址。
我遇到了下面的代码,我不明白为什么任何内存区域的起始/结束地址不等于mm_struct-〉stack_start值。如果能帮助我理解这一点,我将不胜感激。谢谢
加载已编译内核模块的一些结果:
VMA编号14:从0x 7 fff 4 bb 68000开始,到0x 7 fff 4 bb8 a000结束,15号虚拟主机:从0x 7 fff 4 bbfc 000开始,到0x 7 fff 4 bbfe 000结束,16号虚拟主机:开始于0x 7 fff 4 bbfe 000,结束于0x 7 fff 4 bc 00000代码段开始= 0x 400000,结束= 0x 400854数据段开始= 0x 600858,结束= 0x 600 a94堆栈段开始= 0x 7 fff 4 bb88420
可以发现堆栈段开始(0x 7 fff 4 bb88420)属于vma编号14,但我不知道地址是否不同。
内核模块源代码:

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/mm.h>

static int pid_mem = 1;

static void print_mem(struct task_struct *task)
{
        struct mm_struct *mm;
        struct vm_area_struct *vma;
        int count = 0;
        mm = task->mm;
        printk("\nThis mm_struct has %d vmas.\n", mm->map_count);
        for (vma = mm->mmap ; vma ; vma = vma->vm_next) {
                printk ("\nVma number %d: \n", ++count);
                printk("  Starts at 0x%lx, Ends at 0x%lx\n",
                          vma->vm_start, vma->vm_end);
        }
        printk("\nCode  Segment start = 0x%lx, end = 0x%lx \n"
                 "Data  Segment start = 0x%lx, end = 0x%lx\n"
                 "Stack Segment start = 0x%lx\n",
                 mm->start_code, mm->end_code,
                 mm->start_data, mm->end_data,
                 mm->start_stack);
}

static int mm_exp_load(void){
        struct task_struct *task;
        printk("\nGot the process id to look up as %d.\n", pid_mem);
        for_each_process(task) {
                if ( task->pid == pid_mem) {
                        printk("%s[%d]\n", task->comm, task->pid);
                        print_mem(task);
                }
        }
        return 0;
}

static void mm_exp_unload(void)
{
        printk("\nPrint segment information module exiting.\n");
}

module_init(mm_exp_load);
module_exit(mm_exp_unload);
module_param(pid_mem, int, 0);

MODULE_AUTHOR ("Krishnakumar. R, rkrishnakumar@gmail.com");
MODULE_DESCRIPTION ("Print segment information");
MODULE_LICENSE("GPL");
jgwigjjp

jgwigjjp1#

看起来start_stack是 initial 堆栈指针地址。它是在程序执行时由内核计算的,并且基于可执行文件中给出的堆栈段地址。我认为它在之后根本不会更新。系统至少在一个示例中使用start_stack:以识别哪个VMA表示“堆栈”(当提供X1 M0 N1 X时),因为包含该地址的VMA保证包含(主)堆栈。
但请注意,这只是“主”(初始)线程的堆栈;多线程程序也将具有其它栈--每个线程一个栈。由于它们都共享相同的地址空间,所以所有线程将显示相同的VMA集,我想你会发现它们也都有相同的start_stack值,但是只有主线程的堆栈指针在主堆栈vma中,其他线程都有自己的堆栈vma--这样每个线程S堆栈可以独立地增长。

f4t66c6m

f4t66c6m2#

通常,一个进程有一个mm_struct,但有许多vm_area_struct,每个都响应一个mmaped区域。
例如,在32位系统中,一个进程有4GB的虚拟地址空间,所有的虚拟地址空间都由mm_struct指向,但是在4GB空间内可以有很多区域,每个区域都由一个vm_area_struct指向,并且这个区域受到vm_area_struct-〉start和vm_area_struct-〉end的限制,所以,显然,mm_struct结构包含vm_area_struct的列表。
Here为详细介绍。

相关问题