Linux/Unix内存管理
(1)内存分配和回收的函数(运算符)
用户层:
C++ -> new 分配 delete 回收 (关键字)
C -> malloc() 分配 free() 回收 (函数)
Unix系统函数 -> brk() sbrk()
Unix系统函数 -> mmap() munmap()
内核层:
Unix系统函数 -> kmalloc()
(2)进程的内存空间
程序:存在硬盘上的可执行文件(静的),进程:在内存中运行的程序(动的)。
程序如果要运行,最基本的硬件是:CPU(运算)和内存(存储数据),CPU只能直接访问内存,不能直接访问硬盘,硬盘上的程序如果需要运行,首先,加载到内存中,内存中运行的程序叫 进程
进程的内存空间:
1)代码段/区(只读区) - 存储函数的代码,函数指针就是函数在代码区的首地址 **只读**
2)全局区/数据段(读写都可以) - 初始化的全局变量、static变量
3)BSS段 - 未初始化的全局变量,BSS段在main()执行之前会自动清0,未初始化的局部变量每次打印都是不同的值,未初始化的全局变量打印全是0
4)堆区 - 也叫自由区,程序员全权掌控堆区,如果堆区内存的分配和回收出现问题,引发内存的泄露,malloc()/free()针对堆区内存
5)栈区 - 系统自动管理,函数的参数,局部变量(非static)
6)只读常量区 - 所有字符串的字面值""都在只读区,const修饰的全局常量,const修饰的局部变量仍然在栈区
下面举个例子:
char* s = "abcd"; //只读常量区
s[0] = 'a'; //修改常量将引发错误
Unix/Linux内存的管理机制
Unix/Linux使用虚拟内存地址技术,程序员接触到的都不是真正的物理内存地址,而是虚拟内存的地址。32位系统中,每个进程都有0-4G的虚拟内存地址,本质上就是一个整数,这个整数先天是不能存储数据的,否则引发 段错误。
虚拟内存地址只有映射了物理内存/硬盘文件后,才能存储数据,虚拟内存地址本身不占用物理内存,但映射以后就占用物理内存/硬盘文件了。
虚拟内存地址分为用户空间和内核空间,0-3G是用户空间(0xC0000000),3G-4G是内核空间,用户空间是不能直接访问内核空间,malloc发生在用户空间,但通过系统提供的函数可以进入内核空间。
内存地址的基本单位是 字节,内存映射的基本单位是内存页,一个内存页 4096(4k)字节,映射一定是4k的整数倍,虽然内存有些许浪费,但是效率得到了提高。
内存页可以用 getpagesize()函数获取,主流的操作系统可以用内存页都是4k。
举报/反馈