进程之间同样的虚拟地址对应 不同的物理内存。
存管理API
包含头文件#include <unistd.h>
1、函数void *sbrk(intptr_t increment/*内存增量,单位字节*/);它返回上一次调用sbrk/brk函数后的末尾指针,失败返回-1;
increment取值:
如果内存增量为0,则返回当前位置指针;内存增量可正可负,如果为正数,指针向后移动,增加内存空间;如果为负数,指针向前移动,并释放内存空间。
函数工作原理:内部维护一个指针,指向当前堆内存最后一个字节的下一个位置。sbrk函数根据增量参数调整该指针的位置,同时返回该指针被调整之前的位置。若发现页耗尽或空闲,则会自动追加或解除页映射。
2、函数int brk(void *end_data_segment/*内存块尾地址*/);成功返回0,失败返回-1。
函数工作原理:内部维护一个指针,指向当前堆内存最后一个字节的下一个位置。brk函数根据指针参数设置该指针的位置。若发现页耗尽或空闲,则自动追加或解除页映射。
brk/sbrk 底层需要维护一个位置
实例:
(1)malloc函数演示:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int *p1 = (int *)malloc(sizeof(int));
int *p2 = (int *)malloc(sizeof(int));
printf("%p\n",p1); //0x8491008
printf("%p\n",p2); //0x8491018
//malloc分配内存时会有多余的空间存储一些额外的信息,在使用free释放时会使用.如果该信息被破坏,将导致free失败
printf("每页%d个字节\n",getpagesize()); //每页4096个字节
free(p2);
// p1[3] = 0; //破坏存储的额外信息
free(p1);
p1 = NULL;
p2 = NULL;
return 0;
}
(2)malloc函数的实现:
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
// 内存控制块
typedef struct mem_control_block {
bool free; // 自由标志
struct mem_control_block* prev; // 前块指针
size_t size; // 本块大小
} MCB;
// 桟顶指针
MCB* g_top = NULL;
// 分配内存
void* mymalloc (size_t size) {
MCB* mcb;
for (mcb = g_top; mcb; mcb = mcb->prev)
if (mcb->free && mcb->size >= size)
break;
if (! mcb) {
mcb = sbrk (sizeof (MCB) + size);
if (mcb == (void*)-1)
return NULL;
mcb->prev = g_top;
mcb->size = size;
g_top = mcb;
}
mcb->free = false;
return mcb + 1;
}
// 释放内存
void myfree (void* ptr) {
if (! ptr)
return;
MCB* mcb = (MCB*)ptr - 1;
mcb->free = true;
for (mcb = g_top; mcb->prev; mcb=mcb->prev)
if (! mcb->free)
break;
if (mcb->free) {
g_top = mcb->prev;
brk (mcb);
}
else if (mcb != g_top) {
g_top = mcb;
brk ((void*)mcb + sizeof (MCB) + mcb->size);
}
}
typedef struct student{
int id;
char name[30];
char gender[10];
int age;
}Student;
int main(void){
Student* stu = (Student*)mymalloc(sizeof(Student));
printf("Please input the id of student:");
scanf("%d",&(stu->id));
printf("Please input the name of student:");
scanf("%s",stu->name);
printf("Please input the gender of student:");
scanf("%s",stu->gender);
printf("PLease input the age of student:");
scanf("%d",&(stu->age));
printf("ID:%d, Name:%s, Gender:%s, Age:%d.\n",stu->id,stu->name,stu->gender,stu->age);
myfree(stu);
return 0;
}
MAP_LOCKED - 锁定映射区域
成功返回0,失败返回-1。
实例:
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
struct Emp{
int id;
char name[20];
double sal;
};
int main(){
int fd=open("emp.dat",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd==-1) perror("open"),exit(-1);
ftruncate(fd,sizeof(struct Emp)*3);//指定文件大小
void* p = mmap(0,sizeof(struct Emp)*3,
PROT_READ|PROT_WRITE,
MAP_SHARED,//写入文件
//MAP_PRIVATE,//不会把内容写入文件,只有本进程使用
fd,0);
struct Emp* pe = p;
pe[0].id = 100;
strcpy(pe[0].name,"liubei");
pe[0].sal = 200000;
pe[1].id = 200;
strcpy(pe[1].name,"guanyu");
pe[1].sal = 150000;
pe[2].id = 300;
strcpy(pe[2].name,"zhangfei");
pe[2].sal = 120000;
munmap(p,sizeof(struct Emp)*3);
close(fd);
return 0;
}
几个动态内存分配函数区别: