JackieLau |
|
||
请问各位兄弟: 我看内核的链接脚本和System.map中,没有发现内核的栈的设置地址(而在像Bootloader中的链接脚本里面一般会指定栈的地址,在初始化的时候就把SP设置到这个地址)。 另外,我还想问,内核态的内存预留的堆和栈各有多大?在哪里设置的? 多谢各位! -------------------- |
|||
coly |
|
||
我个人理解,不一定正确。而且我的理解经常错误,呵呵。 内核中的栈和堆与应用程序的栈和堆,概念上相同,但是在实现和使用上不太一样。 linux下应用程序的栈和堆都是基于虚拟内存的地址空间的概念的,就是对应内核中的vma的list。在应用程序中,栈和堆的起始地址是有约定的。 但是内核本身没有另外一个更高层的程序来管理内核的地址空间,所以内核空间的栈的组织,和应用程序有所不同。内核的栈如果溢出时,不能像应用程序那样产生一个page fault,然后分配新的地址空间,继续使用。内核的栈如果溢出,没有人知道,除非溢出的地方影响了运行,让程序crash。 而内核本身更没有堆,堆在我理解是针对应用程序的,堆内的线性地址空间靠libc中的malloc和free来管理。堆的空间的扩大靠brk()系统调用。而内核的内存使用,get_free_pages来实现的(虽然上层封装了kmalloc和vmalloc),这个基本上是自己管理自己,由于Linux内核还不支持自己的swapping,所以内核如果找不到可用的页框了,也就没办法了。 最后,Linux下应用程序的堆起始地址,一般就是在bss后面开始。也许需要某个单位的地址对齐,也许中间还有一些堆的管理数据结构,但是大致就是这个位置。Linux下栈的起始,有两种方式:1,从3G往下某一个地址开始,往下生长,直到和堆碰上;2,在应用程序线性地址的低端,即文本段之前的低端地址空间的某一个位置开始,然后往下生长(这种情况下,栈的起始位置和文本段的起始位置中间会有一些空隙,主要是用来放置参数用的)。 而内核中,就比较随便了。首先内核中分配数据的可用页框区域,没有固定的起始地址。get_free_pages最初能获得哪个页框,完全取决于buddy系统的初始化算法,以及bootmem中内存分配的布局。这个和堆有点点不一样。 上面是我的主要的理解,可能具体的编码实现在linux中会有所差异。希望没有错误,呵呵。因为我理解有限,文字中的错误是经常和正常的。 -------------------- |
|||
JackieLau |
|
||
Coly,非常感谢你,多谢指点,也不必这么谦虚 :) 上面你说了,内核的栈起始是在BSS段的开始,那么结束位置呢? 另外,我说的内核的堆就是用Kmalloc管理的那块内存,它的范围是多少呢? 请各位大侠们赐教。 -------------- 我这个问题的引出是这样的,在单板上传给内核参数的内存大小是40M(mem=40M),然后在系统起来以后,看到的内存总大小却是36.7M,那剩下的内存去哪里了? 从System.map中可以看出来,有3.16M是作为内存的代码段数据段BSS段,及初始化数据段等。 还有另外一个问题,在System.map中可以看出,有一些初始化的代码与数据段,这些东西使用完后,会不会被重新利用起来呢? 上面算是我的问题的引论吧? 再次感谢Coly :) -------------------- |
|||
JackieLau |
|
||
补充: -------------------- |
|||
coly |
|
||
1,“上面你说了,内核的栈起始是在BSS段的开始,那么结束位置呢? ” 关于最初问题的引出,我认为得看内核的内存初始化,以及显示数据的计算办法。我对嵌入式不熟悉,但是仅仅数字比数字是不行的。最好看看代码是如何根据你的40M得出36.7M的。 另外,兄弟我有一个建议,就是在做结论之前,最好能先验证一下自己的结论。不然这种风格真的会死人的,不是害死别人,就是把自己搞了。 希望我的语气没有严厉(我没有那个意思,只是看到你将自己的理解说成是我的话,后背有点凉)。其实我也是菜鸟,在论坛上跟大家互相请教的。一起进步,一起进步 -------------------- |
|||
leviathan |
|