想学习一些内存中堆栈的底层处理,知道的说下

DontKissBossAss 2011-03-31 04:42:59
malloc一个内存在windows中是在虚拟内存中开一个地方,等进程获取到时间片的时候,虚拟内存怎么交换到内存,CPU又怎么独到寄存器,


哪有这方面的知识介绍的。 求教。
...全文
262 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
DontKissBossAss 2011-07-09
  • 打赏
  • 举报
回复
不过,在这之前,看了Intel汇编语言程序设计。 那个累。
DontKissBossAss 2011-07-09
  • 打赏
  • 举报
回复
现在已经清楚了,看完了 CSAPP的第10章, 对linux\windows 了解不少,最起码心底的疑惑没了, 最大的收获就是,看windows核心编程,没障碍了, 一口气看N章。 反过头来在写书上的代码,也很轻松。谢谢楼上各位。
辰岡墨竹 2011-04-04
  • 打赏
  • 举报
回复
呵呵,在Windows下,malloc总是在进程的默认堆里分配的,用的是API的HeapAlloc/HeapFree函数,堆机制本身就是用来管理小块内存的,默认堆是1MB,会自动增长。而CRT的malloc在上面加了一层自己的机制,所以更慢,malloc并不去管那些内存地址的细节问题,HeapAlloc返回什么它就用什么。
Windows下要想申请整页内存,只有通过VirtualAlloc来分配,堆机制也是依靠它来分配的。你们上面讨论的一对关于触发虚拟内存页面之类的问题都是VirtualAlloc和其之下的内核机制来负责的。
Linux下的malloc应该是靠INT 80H系统调用分配的内存页,它完全需要自己来管理。
cxyOOOO 2011-04-04
  • 打赏
  • 举报
回复
crt函数是和系统以及其实现相关。

malloc使用私有堆(该堆在_heap_init中创建,句柄保存在_crtheap中)
以下是VC8中调malloc的动作。

使用系统模式的malloc调用RtlAllocateHeap,跟踪入。
在调ZwAllocateVirtualMemory函数时的打印的调用堆栈:
0012f800 7c96b932 ntdll!NtAllocateVirtualMemory+0xa
0012fa3c 7c98eea0 ntdll!RtlAllocateHeapSlowly+0xe85
0012fac0 7c96b394 ntdll!RtlDebugAllocateHeap+0xaf
0012fcf0 7c938f21 ntdll!RtlAllocateHeapSlowly+0x44
0012ff24 0040f7da ntdll!RtlAllocateHeap+0xe64
0012ff44 00426322 testcpp!malloc+0x7a

ZwAllocateVirtualMemory调KiFastSystemCall转入内核态,修改用户进程的VAD(虚拟地址描述符)

HeapAlloc(即RtlAllocateHeap)的实现可以在ntos\rtl\Heap*.c中(win2k源码, wrk里没找着)
gene639 2011-04-03
  • 打赏
  • 举报
回复
你有没有考虑过malloc会不会失败的情况?程序在malloc时,它能不使用这段内存吗,也许编译都通不过。关键是内核在物理内存不够时会怎么处理,malloc一定会触发内核对内存的回收和交换,如果刚分配完内存,开始读写时它就产生了缺页中断,说明它给你分了一块虚拟内存,所以有必要malloc失败吗?如果有malloc失败的情形,就放心大胆的用肯定分的是物理内存,只不过用着用着有些页就被系统换到磁盘上去了,这时就有了交换swap,内核知道该页有没有在内存里是在页表项中的字段指定的。交换需要磁盘信息,因此也就有了外页表。有的书上也说磁盘块的地址是写在内页表项里的,磁盘的使用跟物理内存的使用一样都需要内核有相应的数据结构的支持。这在书上也是介绍过的,但是到底是怎么实现的,除了操作系统程序员,很少有人知道。
samako 2011-04-03
  • 打赏
  • 举报
回复
作个标记也学习下
HEIYANDIDI 2011-04-03
  • 打赏
  • 举报
回复
晕死~
cxyOOOO 2011-04-03
  • 打赏
  • 举报
回复
上边的malloc指malloc分配大块内存,若是小内存malloc又是另一种情况。(vc)
cxyOOOO 2011-04-03
  • 打赏
  • 举报
回复
win下,
物理内存不够,系统会回收它认为不紧急的页面,再分配给需要的地方。(可以回收于A进程,再分配给A进程)
malloc失败通常是进程地址空间不足的原因,malloc只是划分空间,没有分配实际的物理内存。物理内存分配发生在缺页异常处理中(#PF)。
举个例子这个代码会失败,在vc中会抛出std::bad_alloc,或CMemoryException*(MFC中)
char *p = new char[0x7fffffff];

《深入解析Windows操作系统-Windows Internals》书不错,我推荐潘爱民的《Windows内核原理与实现》。
另外,在wrk或者win2k源码ntos\mm中可以看到实现。
yutaooo 2011-04-01
  • 打赏
  • 举报
回复

先整理一下。这里说的内存指多个区域。
1. 用户已经请求到的,并且使用过的地址范围。
2. 用户已经请求到的,没有使用过的地址范围。
3. malloc()向内核请求到的,没有交付给用户的,空闲区的地址范围。
4. 内核管理的,没有交付给malloc()的地址范围。

注意,我们尽量用地址范围,而不是内存,因为我觉得这是理解的关键。
场景1. 用户调用malloc(),malloc()发现自己有空闲地址能满足用户,则分配给用户。这个分配,是通过chunk的元数据做标记以及重新组织空闲链完成的。
场景2. 用户调用malloc(),malloc()自己空闲地址也不够,则发起系统调用向内核请求。内核交付给malloc(),malloc()有了新地盘后,再向用户交付。

内核交付的内存地址一般是以4k为单位的。

用户现在已经成功向malloc()请求到了地址范围。用户访问这个范围(读或写)。这时候这个范围是否有物理内存支撑呢?不知道。这要看具体情况。
情况1. 注意,4k是个边界。曾经访问过这4k块中的地址。那么,映射已经完成了。有物理内存支撑。
情况2. 4k块中的地址从来没有被访问过。这时候,引发一个异常。这个异常导致,从用户态切换到内核态,进行分页映射。映射完成,再次执行原来引起异常的那条语句。
情况3. malloc()请求到的地址范围,是曾经调用free()还给分配器的,那么已经进行过分页映射了。

操作系统总是尽量拖延分页影射发生的时间。这是因为,1. 如果没有真正访问动作发生,那么有可能访问动作永远不会发生。做了可能白做。2. 影射是非常耗时的,代价太高。尤其是当物理内存短缺时,还会发生swap。这将牵扯另一个更加慢慢慢速的设备,硬盘。

分页影射动作,基本上就是一个在分页表中登记物理内存的动作。
luciferisnotsatan 2011-04-01
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zhao4zhong1 的回复:]

《深入解析Windows操作系统-Windows Internals》
[/Quote]
+1
Meteor_Code 2011-04-01
  • 打赏
  • 举报
回复
386汇编程序设计
DontKissBossAss 2011-04-01
  • 打赏
  • 举报
回复
呵呵,没想到这么多人关心,因为不懂,我描述的非常有问题,除了上边的描述,其实更关心的是什么页交换之类的。
gene639 2011-03-31
  • 打赏
  • 举报
回复
我也一直想了解这个问题,顶!
你是说fork还是malloc,为什么你会关心CPU和寄存器呢?malloc大概是发生在进程的地址空间中,以堆分配,在内核中请求内存,可能会填写页表项和更新PCB,不用程序员管。所以进程自己使用时不会管是不是虚拟内存和实际内存,也不用交换。它就能通过这个指针来存储数据。大概意思可能是这样不能帮你什么,内核管理内存非常复杂一般只有大牛才知道内核是怎么分配内存的,呵呵。
l369294289 2011-03-31
  • 打赏
  • 举报
回复
顶一下。。。。。。。。。
某某9 2011-03-31
  • 打赏
  • 举报
回复
不懂啊
cxyOOOO 2011-03-31
  • 打赏
  • 举报
回复
涉及两个方面:cpu分页机制和操作系统内存管理机制
bluesky12312388 2011-03-31
  • 打赏
  • 举报
回复
malloc一个内存在windows中是在虚拟内存中开一个地方
==============================================
就好比你向学校申请一个自习教室去自习,只有被批准了才行,否则
就是违规的,是要受到处罚的。

进程获取到时间片的时候,虚拟内存怎么交换到内存
=======================
一般来说现在现代CPU是以线程为基本单位分配CPU时间片的,
比如说线程中有访问内存,但这个地址的内容不在逻辑内存中,
那么就产生一个缺页中段,将所需的内容调入内存
(当然也有可能所需的内容在Cache中,那就是直接访问了)

CPU又怎么读到寄存器,
=======================
寄存器属于CPU的一个部件,如果真的要说读的话,
可能CPU在某根内部数据线上产生某个高平电压,然后就读到
寄存器的值了。实际是怎样的,可能去查查CPU构造手册。
走走刀口 2011-03-31
  • 打赏
  • 举报
回复
非技术区回答技术题!
DontKissBossAss 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zhao4zhong1 的回复:]
《深入解析Windows操作系统-Windows Internals》
[/Quote]

谢谢了。这部分的东西会不会windows 和linux 各异呢?
加载更多回复(5)

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧