Linux进程的虚拟地址空间
2015-07-20 11:24
696 查看
1.以32位系统为例,Linux系统中每个进程共有3GB的用户地址空间,当用户调用系统调用时,内核线程会代表进程运行,此时是在内核空间内运行的,故所有进程共享1GB的内核空间. 所以,总的来说,每个进程可用的地址空间共有4GB
2.进程的3GB用户地址空间由下图所示:
![](https://img-blog.csdn.net/20150720093537626)
3.地址映射:
一个程序在经过编译、连接之后形成的地址空间是一个虚拟的地址空间,只有当程序运行的时候才会分配具体的物理空间.由此我们可以得知,程序的虚拟地址相对来说是固定的,而物理地址则随着每一次程序的运行而有所不同.
对于内核空间而言,它与物理内存之间存在一个简单的线性关系,即存在3GB的偏移量.在Linux内核中,这个偏移量叫做PAGE_OFFSET.如果内核的某个物理地址为x,那么对应的内核虚地址就为x+PAGE_OFFSET.
对于用户空间而言,它与物理内存之间的映射远不止这么简单.与内核空间和物理空间的线性映射不同的是,分页机制将虚拟用户空间和物理地址空间分成大小相同的页,然后再通过页表将虚拟页和物理页块映射起来.
4.虚拟地址空间举例:
用户地址空间:
内核地址空间:
本文引述自:http://edsionte.com/techblog/archives/1922
2.进程的3GB用户地址空间由下图所示:
可以看出,进程的用户地址空间从0x00000000--0xbfffffff(2^30+2^31),依次是代码段,数据段,堆,堆栈
3.地址映射:
一个程序在经过编译、连接之后形成的地址空间是一个虚拟的地址空间,只有当程序运行的时候才会分配具体的物理空间.由此我们可以得知,程序的虚拟地址相对来说是固定的,而物理地址则随着每一次程序的运行而有所不同.
对于内核空间而言,它与物理内存之间存在一个简单的线性关系,即存在3GB的偏移量.在Linux内核中,这个偏移量叫做PAGE_OFFSET.如果内核的某个物理地址为x,那么对应的内核虚地址就为x+PAGE_OFFSET.
对于用户空间而言,它与物理内存之间的映射远不止这么简单.与内核空间和物理空间的线性映射不同的是,分页机制将虚拟用户空间和物理地址空间分成大小相同的页,然后再通过页表将虚拟页和物理页块映射起来.
4.虚拟地址空间举例:
用户地址空间:
#include <stdio.h> int data_var = 0; int bss_var; int main(int argc, char *argv[]) { static int static_data_var = 0; static int static_bss_var, static_bss_var2, static_bss_var3; int *malloc_var = malloc(sizeof(int)); int stack_data_var = 0; int stack_bss_var; printf("address main function: %p\n", main); printf("address data: %p\n", &data_var); printf("address bss: %p\n", &bss_var); printf("address static data: %p\n", &static_data_var); printf("address static bass data: %p\n", &static_bss_var); printf("address static bass data2: %p\n", &static_bss_var2); printf("address static bass data3: %p\n", &static_bss_var3); printf("address malloc: %p\n", malloc_var); printf("address stack data: %p\n", &stack_data_var); printf("address stack bss data: %p\n", &stack_bss_var); return 0; } 运行结果: address main function: 0x804844d address data: 0x804a028 address bss: 0x804a03c address static data: 0x804a02c address static bass data: 0x804a030 address static bass data2: 0x804a034 address static bass data3: 0x804a038 address malloc: 0x99b9008 address stack data: 0xbfc17104 address stack bss data: 0xbfc17108 运行结果表明: 数据段中保存的是:已经初始化了的全局变量, static静态变量(不管是已经显示初始化了的还是没有初始化的) bss段中保存的是:没有初始化的全局变量 堆中保存的是:类似malloc这样的函数申请时的动态变量 堆栈中保存的是:函数内部定义的变量(不管是已经初始化了的还是没有初始化的)
内核地址空间:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> //必选 //模块许可声明 MODULE_LICENSE("GPL"); //模块加载函数 static int mm_init(void) { void *getpage_addrres, *kmalloc_address, *vmalloc_address; getpage_addrres = __get_free_page(GFP_KERNEL); kmalloc_address = kmalloc(sizeof(int), GFP_KERNEL); vmalloc_address = vmalloc(sizeof(int)); printk("address get_page: %p\n", getpage_addrres); printk("address kmalloc: %p\n", kmalloc_address); printk("address vmalloc: %p\n 4000 ", vmalloc_address); printk(KERN_ALERT "mm_init success\n"); return 0; } //模块卸载函数 static void mm_exit(void) { printk(KERN_ALERT "mm_exit success\n"); } //模块注册 module_init(mm_init); module_exit(mm_exit); //可选 MODULE_AUTHOR("edsionte Wu"); MODULE_DESCRIPTION("This is a simple example!\n"); MODULE_ALIAS("A simplest example"); 运行结果: address get_page: e1291000 address kmalloc: e11f8780 address vmalloc: f8430000 结果表明: 内核空间的地址都是大于0xc0000000的,也即从(2^31+2^30)开始
本文引述自:http://edsionte.com/techblog/archives/1922
相关文章推荐
- 此时无足够的可用内存,无法满足操作的预期要求,可能是由于虚拟地址空间碎片造成的,请稍后重试
- Ubuntu 命令行修改网络配置方法
- Linux内存空间以及内存管理
- 内核逻辑地址和内核虚拟地址的区别
- 虚拟地址 物理地址 映射
- c语言==进程虚拟地址的划分(5)
- 虚拟内存和虚拟地址
- MMU简介
- Postgresql 配置远程访问, 以及 虚拟机访问物理机上的postgresql 的ip配置
- linux进程内存映象解析
- dm6446的内存地址分析
- Mac上Apache部署本地PHP工程虚拟地址
- linux内存管理器子系统
- 自学ThinkPHP--(二)URL和路由(上)
- 虚拟存储器--虚拟地址与物理地址
- Linux下获取虚拟地址对应的物理地址的方法
- linux 用户空间与内核空间——高端内存详解
- Linux 内核中逻辑地址/虚拟地址/线性地址三者的区别
- linux 进程的虚拟地址和内核中的虚拟地址有什么关系
- linux和windows的进程的虚拟地址空间