导航:首页 > 编程系统 > 0x0linux内存地址分布

0x0linux内存地址分布

发布时间:2023-12-22 09:02:50

『壹』 linux:谁能给我解释下虚拟地址和物理地址的联系

这个问题很大。。。。我尽自己所能给你解释一下吧,如果你不能完全看懂,以后可以回头再翻翻来看。关于虚拟内存的事情,大概是这样的:
首先你要明确什么是虚拟内存。虚拟内存实际上是操作系统对于内存管理的一种方式,比如说,对每个程序而言,它的内存编址都从0x00到0xff,但是实际上,这些内存对应的物理地址,应用程序本身是无法知道的,在这里就可以理解成操作系统对内存管理的一层抽象。
比如,可能进程init的虚拟地址0x00对应了物理地址的0x10,而kthreadd的虚拟地址0x00对应物理地址0x20,etc.
而且虚拟内存也是一种有效的进程间隔离的方式,极大的提升了进程的安全性和操作系统的稳定性,也就是我一个进程不管做什么,都是在它自己的地址空间里做的,不会影响到其他进程和OS。
当然这是理想情况,实际上还有进程间通信啦之类,这就不在这个问题的范围之内了。
而具体怎么把这些虚拟地址对应到物理地址上,这是操作系统做的事情,估计这个也就是你的问题。
----以上是背景1-----
然后我要明确一下:地址总线4位的意思是说内存用4个bit位来表达地址,所以能够index的地址位就是2^0-2^4,也就是0x0到0xf,就是16个bit的内存空间。
然后我们再来细化一下你的例子,就比方说在你的16bit的内存的机器上有1个OS,上面跑着2个程序。一般来说OS会保留地址的高位,比如11-15bit的位置,作为kernel space;然后0-10bit是user space。
在以上的前提下,虚拟内存的效果是:在每一个程序看来,这个程序都有0x0到0xf的地址可以用,并且它们的0xb-0xf都是shared kernel space,然后0x0-0xa都是自己的user space,这样仿佛就有了32个bit的地址一样。这就是你所谓的是用虚拟地址可以使总的地址操作物理地址。至于os是怎么做到这点的,继续往下看。
-----以上是背景2-----
操作系统对每一个进程有一个进程控制块,叫PCB,Process Control Block,里边存储了每一个进程的进程信息,比如说寄存器,file descriptor,还有我们最关心的内存映射信息。每一个进程有一个递增的id号,叫pid,也就是Process IDentifier.
-----以上是背景3-----
进程间切换,也就是说,比如说你一个系统只有1个CPU,但是有两个进程要跑,而且要让我们看起来好像是两个进程同时在跑一样。为什么我要提到这个呢,后面继续看。
-----以上是背景4-----
好,现在来讲如何把虚拟地址映射到物理地址。从程序的角度来看,从malloc开始讲起,比如,在某一时刻,一个进程调用了malloc,在堆(heap)上申请了2bits的空间。实际上这个行为的流程是,程序调用malloc,进入内核模式之后,调用mmap,如果成功,操作系统会从物理地址上取一块2bits的内存,交给应用程序编入虚拟地址空间。更详细一点说,每个进程对内存管理是一个红黑树的结构,也就是说,在每一个进程的PCB,里维护了一颗红黑树,然后动态的将所有的新分配的内存加到这个红黑树里边,以保证程序对每一块内存的访问时间是差不多的。然后不知道你们教材中有没有提到页表(page table),页表也是PCB中的一项,你们教材中应该会对页表有详细的讲解,将如何对内存的地址进行换算,之类的。然后你要明确,页表实际上是红黑树的cache,这样可以加速程序对于常用的内存的访问速度。
以上是操作系统对内存管理的一个大致概括,就是一块物理的内存如何映射成为一块虚拟的内存。
我在背景2中说,两个程序都看到自己有16个bit的虚拟地址,总共有32bit,但是实际上硬件只有16bits,也就是说,不管你在红黑树和页表中怎么映射,一定会有冲突发生,比如,可能物理地址的0x02对应了进程1中的0x04,又在进程2的PCB中映射到了pid2的虚拟地址位0x06上。操作系统如何解决这个矛盾呢,首先在进程pid 1运行的时候,这个0x02对应的是pid1中的0x04;然后这个时候进程切换发生了,pid 2开始运行。当pid2需要用到它的0x04时,os发现0x02这个地址在pid1中也有映射,于是它就把0x02这个地址上的内容存到硬盘上的一个叫swap的空间内,然后把这个地址交给pid2使用。这样就达到了扩大虚拟地址的效果。
但是这样做是有代价的,因为一旦这个page被swap出去,那么在pid1再来调用的时候会发生一系列的miss,从L1 cache miss到 L2 cache miss到L3 cache miss,然后页表miss,memory miss,会对程序的性能造成极大的影响。影响有多大呢,平均来说:
L1 cache hit: 0.5ns
L2 cache hit: 7ns
主内存引用:100ns
顺序从内存中读取1MB:250,000ns
硬盘寻道:10,000,000ns
从硬盘上顺序读取1MB:30,000,000ns
所以你就可以知道这种行为是以极大的性能为代价的。
----讲完啦-----
总的来说这个很大的话题,我刚才所写的东西的就是试图让你对虚拟内存这个东西有一个基本的概念,然后大致的了解内存是如何映射的。就我现在能想到的,对这个虚拟内存话题的讨论还包括多级页表,进程间隔离&通信以及memory fragment。
个人水平有限,如果以上有什么地方说错的或者遗漏的,还请各位多多补充和批评,谢谢。

『贰』 Linux进程虚拟地址空间的分布,以及堆和栈的区别

一、具体分布如图所示:

二、关于堆和栈
(1)分配方式:
栈:由编译器自动分配释放,存放函数的参数回值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆: 一般由程序员分配释放,它的分配方式类似于链表。
(2)申请后系统的响应:
栈:只要所申请的空间小于栈的剩余空间,则系统为程序分配内存,否则栈溢出。
堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,遍历该链表,找出第一个大于所申请空间的节点,然后将其从链表中删除并分配,如果没用完,则系统会把多余的重新放回到链表中。
(3)申请大小的限制:
栈:栈答是高地址向低地址扩展的连续内存,栈的大小一般是2M;
堆:堆是低地址向高地址扩展的不连续内存,堆的大小与计算机有效的虚拟内存有关系。
(4)申请效率:
栈:由系统自动分配,速度较快;
堆:速度慢,容易产生内存碎片;
关于Linux命令的介绍,看看《linux就该这么学》,具体关于这一章地址3w(dot)linuxprobe/chapter-02(dot)html.

『叁』 如何查看Linux内存中的程序所有堆的地址

linux 下面查看内存有多种渠道,比如通过命令 ps ,top,free 等,比如通过/proc系统,一般需要比较详细和精确地知道整机内存/某个进程内存的使用情况,最好通过/proc 系统,下面介绍/proc系统下内存相关的几个文件

单个进程的内存查看 cat /proc/[pid] 下面有几个文件: maps , smaps, status

maps 文件可以查看某个进程的代码段、栈区、堆区、动态库、内核区对应的虚拟地址,如果你还不了解linux进程的内存空间,可以参考这里。

下图是maps文件内存示例

Develop>cat /proc/self/maps
00400000-0040b000 r-xp 00000000 fd:00 48 /mnt/cf/orig/root/bin/cat
0060a000-0060b000 r--p 0000a000 fd:00 48 /mnt/cf/orig/root/bin/cat
0060b000-0060c000 rw-p 0000b000 fd:00 48 /mnt/cf/orig/root/bin/cat 代码段
0060c000-0062d000 rw-p 00000000 00:00 0 [heap] 堆区
7f1fff43b000-7f1fff5d4000 r-xp 00000000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff5d4000-7f1fff7d3000 ---p 00199000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d3000-7f1fff7d7000 r--p 00198000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d7000-7f1fff7d9000 rw-p 0019c000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d9000-7f1fff7dd000 rw-p 00000000 00:00 0
7f1fff7dd000-7f1fff7fe000 r-xp 00000000 fd:00 2554 /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9f9000-7f1fff9fd000 rw-p 00000000 00:00 0
7f1fff9fd000-7f1fff9fe000 r--p 00020000 fd:00 2554 /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9fe000-7f1fff9ff000 rw-p 00021000 fd:00 2554 /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9ff000-7f1fffa00000 rw-p 00000000 00:00 0
7fff443de000-7fff443ff000 rw-p 00000000 00:00 0 [stack] 用户态栈区
7fff443ff000-7fff44400000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 内核区

有时候可以通过不断查看某个进程的maps文件,通过查看其虚拟内存(堆区)是否不停增长来简单判断进程是否发生了内存溢出。

maps文件只能显示简单的分区,smap文件可以显示每个分区的更详细的内存占用数据

下图是smaps文件内存示例, 实际显示内容会将每一个区都显示出来,下面我只拷贝了代码段和堆区,

每一个区显示的内容项目是一样的,smaps文件各项含义可以参考这里

Develop>cat /proc/self/smaps
00400000-0040b000 r-xp 00000000 fd:00 48 /mnt/cf/orig/root/bin/cat
Size: 44 kB 虚拟内存大小
Rss: 28 kB 实际使用物理内存大小
Pss: 28 kB
Shared_Clean: 0 kB 页面被改,则是dirty,否则是clean,页面引用计数>1,是shared,否则是private
Shared_Dirty: 0 kB
Private_Clean: 28 kB
Private_Dirty: 0 kB
Referenced: 28 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB 处于交换区的页面大小
KernelPageSize: 4 kB 操作系统一个页面大小
MMUPageSize: 4 kB 体系结构MMU一个页面大小
Locked: 0 kB

0060c000-0062d000 rw-p 00000000 00:00 0 [heap]
Size: 132 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 8 kB
Referenced: 8 kB
Anonymous: 8 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB

下图是status文件内存示例, 加粗部分是内存相关的统计,

Develop>cat /proc/24475/status
Name: netio 可执行程序的名字
State: R (running) 任务状态,运行/睡眠/僵死
Tgid: 24475 线程组号
Pid: 24475 进程id
PPid: 19635 父进程id
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256 该进程最大文件描述符个数
Groups: 0
VmPeak: 6330708 kB 内存使用峰值
VmSize: 268876 kB 进程虚拟地址空间大小
VmLck: 0 kB 进程锁住的物理内存大小,锁住的物理内存无法交换到硬盘

VmHWM: 16656 kB
VmRSS: 11420 kB 进程正在使用的物理内存大小
VmData: 230844 kB 进程数据段大小
VmStk: 136 kB 进程用户态栈大小
VmExe: 760 kB 进程代码段大小
VmLib: 7772 kB 进程使用的库映射到虚拟内存空间的大小
VmPTE: 120 kB 进程页表大小
VmSwap: 0 kB
Threads: 5
SigQ: 0/63346
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000001000000
SigCgt: 0000000180000000
CapInh: 0000000000000000
CapPrm: ffffffffffffffff
CapEff: ffffffffffffffff
CapBnd: ffffffffffffffff
Cpus_allowed: 01
Cpus_allowed_list: 0
Mems_allowed: 01
Mems_allowed_list: 0
voluntary_ctxt_switches: 201
nonvoluntary_ctxt_switches: 909

可以看到,linux下内存占用是一个比较复杂的概念,不能

简单通过一个单一指标就判断某个程序“内存消耗”大小,原因有下面2点:

进程所申请的内存不一定真正会被用到(malloc或mmap的实现)
真正用到了的内存也不一定是只有该进程自己在用 (比如动态共享库)

关于内存的使用分析及本文几个命令的说明也可以参考这里

下面是查看整机内存使用情况的文件 /proc/meminfo

Develop>cat /proc/meminfo
MemTotal: 8112280 kB 所有可用RAM大小 (即物理内存减去一些预留位和内核的二进制代码大小)
MemFree: 4188636 kB LowFree与HighFree的总和,被系统留着未使用的内存
Buffers: 34728 kB 用来给文件做缓冲大小
Cached: 289740 kB 被高速缓冲存储器(cache memory)用的内存的大小
(等于 diskcache minus SwapCache )
SwapCached: 0 kB 被高速缓冲存储器(cache memory)用的交换空间的大小
已经被交换出来的内存,但仍然被存放在swapfile中。
用来在需要的时候很快的被替换而不需要再次打开I/O端口
Active: 435240 kB 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,
除非非常必要否则不会被移作他用
Inactive: 231512 kB 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径.
Active(anon): 361252 kB
Inactive(anon): 120688 kB
Active(file): 73988 kB
Inactive(file): 110824 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB 交换空间的总大小
SwapFree: 0 kB 未被使用交换空间的大小
Dirty: 0 kB 等待被写回到磁盘的内存大小
Writeback: 0 kB 正在被写回到磁盘的内存大小
AnonPages: 348408 kB 未映射页的内存大小
Mapped: 33600 kB 已经被设备和文件等映射的大小
Shmem: 133536 kB
Slab: 55984 kB 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗
SReclaimable: 25028 kB 可收回Slab的大小
SUnreclaim: 30956 kB 不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
KernelStack: 1896 kB 内核栈区大小
PageTables: 8156 kB 管理内存分页页面的索引表的大小
NFS_Unstable: 0 kB 不稳定页表的大小
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 2483276 kB
Committed_AS: 1804104 kB
VmallocTotal: 34359738367 kB 可以vmalloc虚拟内存大小
VmallocUsed: 565680 kB 已经被使用的虚拟内存大小
VmallocChunk: 34359162876 kB
HardwareCorrupted: 0 kB
HugePages_Total: 1536 大页面数目
HugePages_Free: 0 空闲大页面数目
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB 大页面一页大小
DirectMap4k: 10240 kB
DirectMap2M: 8302592 kB

『肆』 Linux的内核空间和用户空间是如何划分的(以32位系统为例)

Linux将4G的地址划分为用户空间和内核空间两部分。在Linux内核的低版本中(2.0.X),通常0-3G为用户空间,3G-4G为内核空间。这个分界点是可以可以改动的。
正是这个分界点的存在,限制了Linux可用的最大内存为2G.而且要通过重编内核,调整这个分界点才能达到。实际上还可以有更好的方法来解决这个问题。由于内核空间与用户空间互不重合,所以可以用段机制提供的保护功能来保护内核级代码。
2.2.X版的内核对此进行了改动。这样内核空间扩张到了4G。从表面上看内核的基地址变为了0,但实际上,内核通常仍在虚址3G以上。
用户空间在2.2.X中从直观上变为0-4G,让人迷惑,不是可以直接访问内核了?
其实不然,同过使用页机制提供的保护,阻止了用户程序访问内核空间。

windows是使用的一个开关设置的,一般是1G,设置过开关之后,用花空间就可以达到3G

另外,附上一片文章吧,这个是64位系统上面的。。。希望能给你启发~~~试着编译下内核吧!
http://www.linuxidc.com/Linux/2011-03/33764.htm

『伍』 怎么查看linux 系统的内存分布

top命令能显示系统复内制存。
目前常用的Linux下查看内容的专用工具是free命令。
下面是对内存查看free命令输出内容的解释:
total:总计物理内存的大小。
used:已使用多大。
free:可用有多少。
Shared:多个进程共享的内存总额。
Buffers/cached:磁盘缓存的大小。

阅读全文

与0x0linux内存地址分布相关的资料

热点内容
win10改变文件格式 浏览:475
linux中的物理地址和虚拟地址 浏览:493
有哪些app可以接游戏订单 浏览:472
苹果硬盘数据恢复要多少钱 浏览:394
js绑定下拉框数据库数据 浏览:448
cad文件怎么复制到另一个文件里边 浏览:858
dxp钻孔文件 浏览:631
iphone大悦城换机 浏览:538
找结婚对象上什么网站 浏览:974
学生信息管理系统程序设计报告 浏览:640
微信文件怎么删除怎么恢复 浏览:407
编程程序怎么复制 浏览:467
文件更改 浏览:327
冰点文件路径 浏览:730
软件一点开文件就关闭 浏览:88
网络如何把人捧红 浏览:961
软件传输文件 浏览:184
密码记录器ios 浏览:412
两个电脑数据怎么一样 浏览:829
顺丰有什么买东西的app 浏览:377

友情链接