每个程序提供了4G的访问能力
逻辑地址与物理地址关联才有意义:过程称为内存映射.
背景:越界访问不一定会产生断错误
访问的虚拟内存地址没有与物理内存地址映射一定会出现段错误
1 brk/sbrk 内存映射函数
补充: 帮助手册
man 节 关键字
1-8节
1:Linux系统(shell)指令
2:系统函数
3:标准C函数
7:系统编程帮助 man tcp ,man icmp ,man socket
分配释放内存:
void* sbrk(int increment) //返回空间地址
int brk(void *addr) //分配空间 释放空间
应用:
1 使用sbrk 分配空间
2 使用sbrk得到没有映射的虚拟地址
3 使用brk分配空间
4 使用brk释放空间
理解:
void* sbrk(int size) //使用相对位置进行分配和释放
sbrk 与 brk 后台系统维护一个指针,增加这个指针相当与分配内存,减小这个指针相当与释放内存
指针默认是null。
调用sbrk,判断指针是否是0 ,是:1初始化指针(一页的起始地址) 2返回指针
3同时把指针+size(若此地址未映射,则先映射一页空间)
,否:1返回指针 2 指针位置+size
sbrk(a) 用于分配a字节的空间, 返回值是这个空间的起始地址
sbrk(-a) 用于释放a字节的空间
sbrk(0) 用于取得目前指针的位置
失败返回 (void *)(-1)
int brk(void *addr) //使用绝对地址进行分配和释放
将指针设置在addr,addr以前空间都被分配出来。addr一般通过sbrk(0)来获得
若未映射则先映射
失败返回-1
#include <stdio.h> #include <unistd.h> int main() { int *p1 = sbrk(4); // 返回空闲地址 内部指针+4 int *p2 = sbrk(200);// 返回内部指针 内部指针+200 int *p3 = sbrk(0); //返回内部指针 printf("%p\n",p1); printf("%p\n",p2); printf("%p\n",p3); /* 0x84fb000 0x84fb004 0x84fb0cc */ printf("pid:%d\n",getpid()); while(1) {} }
#include <stdio.h> #include <unistd.h> int main() { int *p1 = sbrk(0); // 返回空闲地址 没分配地址 brk(p1+100); //分配一个空间:发现是未映射的,先映射一个页,再分配100字节(参数是分配空间的结束地址) *(p1+100) = 80; *(p1+1000) = 800; // 越界访问也是可以的 brk(p1+1); //将分配的空间的尾地址设置为p1+1 *(p1+100) = 99; //越界访问仍然可以 brk(p1); //继续释放,将分配的空间的尾地址设置为p1 因为这个页里面分配0空间,这个页不再被映射 *(p1) = 100; //段错误 地址未映射 }
/* 找出1-10000中的素数,存在内存中,最后再打印出来。 */ #include <stdio.h> #include <unistd.h> #include <math.h> int main() { int *p_start ,*p_end; p_start = sbrk(0); p_end = p_start; int i,j; int is_sushu; for(i = 2; i < 1001; i++) { is_sushu = 1; for( j=2; j<sqrt(i); j++) { if( i%j ==0 ) { is_sushu = 0; break; } } if(is_sushu) { brk(p_end+1); *p_end = i; p_end +=1; } } int *p = p_start; while(p!= p_end) { printf("%d ",*p); p++; } brk(p_start); printf("\n"); }
#include <stdio.h> #include <sys/mman.h> #include <stdlib.h> //NULL宏 #include <unistd.h> //getpagesize() main() { int *p =mmap( NULL, getpagesize(), PROT_READ|PROT_WRITE, //只写WRITE时可以读,只写READ时不可以写 段错误 MAP_ANONYMOUS|MAP_SHARED, 0,0); *p = 20; *(p+1) = 30; *(p+2) = 40; printf("%d\n",p[2]); //40 printf("%p\n",p); munmap(p,4096); printf("pid:%d\n",getpid()); while(1){} }
3总结
智能指针
最方便使用STL new
STL
new
malloc 小而多的数据
效率最高:brk mmap
brk/sbrk 同类型的大块数据,根据需要动态移动指针
mmap/munmap 控制内存访问 内存直接向使用文件映射 控制内存共享