Unix/Linux的内存分配

原创 2013年12月04日 23:10:12
程序员所接触的都是虚拟内存地址。每个进程都有0-4G的虚拟内存地址,本质上就是一个整数。这个整数

先天是不能够存储数据的,否则会引发段错误。虚拟内存地址,只有映射零物理内存/硬盘文件后,才能存

储数据,才占据内存。

虚拟内存地址分为用户空间和内核空间。0-3G为用户空间,3-4G是内核空间。用户空间不能直接访问内核空间,但可以通过系统提供的函数进入内核空间。内存地址的基本单位是字节,内存映射的基本单位是内存页,一个内存页是4k(或者4k的倍数)。

内存分配和回收的函数(运算符)
STL          -》 自动分配,自动回收
|
C++          -》new ,delete
|
c语言        -》malloc() free()
|
Unix系统函数 -》brk() sbrk()
|
Unix系统函数 -》mmap(),munmap()           用户层
————————————————————————————
     |
Unix系统函数 -》kmalloc()                 内核层

1)malloc 和 free

malloc只有在第一次时映射内存,一次映射33个内存页。如果用完, 才再次映射。
如果系统映射超过33页,系统就会映射稍多一点内存。

需要注意的是:

malloc分配内存时,系统会额外占用一些空间,用于存储下一个空间的 附加信息。

	int *p1 = malloc(4); //内存映射,映射33个内存页
	int *p2 = malloc(4);//只分配,不再映射内存
	int *p3 = malloc(4);
	int *p4 = malloc(12);
	printf("%p %p %p %p \n",p1,p2,p3,p4);//堆之间的地址并没有连续
//p1地址前面存放着附加信息,将附加信息清零  ==》错误:已放弃,核心已转移	
	*(p1 -1) = 0; 。
        free(p1);
free()一定释放虚拟内存,但是不保证解除物理内存的映射,而且最后的33个内存页是无法free的,进程
结束才能解除最后的33个内存页。为了提高效率,用空间换时间。

例如,我首先分配内存

void *p = malloc(1);//此时系统一次性映射了33个内存页
free(p);  //此时并没有解除物理内存的映射.

2) sbrk 和 brk

sbrk()和brk()底层维系了一个位置。通过位置的移动来分配和回收内存。
void sbrk(intptr_T increment)

increment 移动增量负数逆向移动(释放内存),正数向前移动(分配内存),

为0返回当前位置。成功返回移动之前的位置,失败返回零。
sbrk实打实的每次一次分配一页空间,如果超出一页就再分配一页。

        char *p_num = sbrk(4);//分配了四个字节的内存,返回首地址
	*p_num = 100;
	printf("%d\n",*p_num);  //打印出100
	sbrk(-4);//释放3个字节内存,返回值没有意义
brk 函数决定了所分配空间的结尾地址.如下:

	void *p = sbrk(0);//返回当前地址,并不映射内存。
	brk(p+4); //分配了四个字节,映射了一页地址。
	brk(p+8); //重新分配四个字节
	brk(p+4);//回收四个字节 
sbrk用来分配内存方便,而brk用来释放内存更方便.(两个函数都可以用来分配和释放内存)
//分配空间存放int
	int *pi = (int*)sbrk(4);
	*pi = 100;
//分配空间存放double
	double *pd = (double*)sbrk(8);
	*pd = 1.0;
//分配空间存放string
 	char *p_str = (char*)sbrk(6);
	strcpy(p_str,"abcde");
//释放所有空间
	brk(pi);
3)mmap,munmap

用来映射或者取消映射.代码如下:

#include<sys/mman.h>
#include<unistd.h>
#include<string.h>
int main()
{
	void *p_map = mmap(0,  //内核选择虚拟首地址
	1,  //映射的字节数,不足内存页补足
	PROT_READ | PROT_WRITE,//读写权限
	MAP_SHARED | MAP_ANONYMOUS,//共享,匿名
	-1,0);  //映射一页内存
	if( p_map == MAP_FAILED)
	{
		perror("mmap");
		return -1;
	}
	int *pi = p_map;
	*pi = 100;

	strcpy(pi + 4,"kongdeju"); //证明映射了一页。
	printf("%d,%s\n",*pi,(char*)(pi + 4));
	munmap(p_map,1);//取消映射
	return 0;
}




相关文章推荐

linux c内存分配函数介绍

  • 2013年08月20日 11:40
  • 24KB
  • 下载

linux内核内存分配方式

  • 2012年02月02日 09:58
  • 184KB
  • 下载

linux-内存分配和动态库静态库

1.内存分配:   在linux中特有的内存分配方式有sbrk和brk,还有mmap(分配)和munmap(释放)。 函数原型分别为: #include //所在头文件 int brk(void ...

Linux常见内存分配函数

  • 2014年02月21日 20:17
  • 134KB
  • 下载

Linux C 动态内存分配--malloc,new,free及相关内容

一、malloc()和free()的基本概念以及基本用法: 1、函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内...

linux 内存分配机制

这几天在观察apache使用内存情况,所以特意了解了下linux的内存机制,发现一篇写得还不错。转来看看。 一般来说在ps aux中看到的rss就是进程所占用的物理内存。但是如果将所有程序的rss加...
  • koozxcv
  • koozxcv
  • 2015年10月28日 17:02
  • 1442

简述Linux内存分配--伙伴系统 原理

Linux内存分配——伙伴系统 目的:最大限度的降低内存的碎片化。 原理: 1.将内存块分为了11个连续的页框块(1,2,4,8....512,1024),其中每一个页框块中用链表将...

Linux 系统编程手册第7章-内存分配

1.在堆上分配内存: a.所谓堆,是一段长度可变的连续虚拟内存。开始于进程未初始化数据段末尾。通常将堆的当前边界称为program break。系统提供两个函数来调整program break,#i...

常见的Linux内核中内存分配函数

常见的Linux内核中内存分配函数1.原理说明  Linux内核中采 用了一种同时适用于32位和64位系统的内 存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系 统中,用到了四级页...

linux内核内存分配(二、struct slab和struct kmem_cache)

前一篇blog linux内核内存分配(一、基本概念) 主要是分析linux内核内存的分配和物理页分配函数接口。但是在实际的操作中,不一定所有内存申请都需要一个物理页,很多只是需要分配几K大小的内存就...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Unix/Linux的内存分配
举报原因:
原因补充:

(最多只允许输入30个字)