Linux实验心得——内存管理

设计二——内存管理

一、实验目的

1. 了解linux 系统的内存机制、虚拟内存管理、分页和分段机制;

2. 掌握malloc,realloc,free,calloc 函数的使用

3. 了解怎样使用物理内存和swap 分区。

4. 了解malloc,realloc,free 的实现方法,掌握linux 的内存分配算法。

 

 

二、预备知识

1.malloc函数

原型:extern void *malloc(unsigned int num_bytes);   

头文件:在TC2.0中可以用malloc.h或 alloc.h (注意:alloc.h 与 malloc.h 的内容是完全一致的),而在Visual C++6.0中可以用malloc.h或者stdlib.h。   

功能:分配长度为num_bytes字节的内存块   

返回值:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。   

说明:关于该函数的原型,在旧的版本中malloc返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。   

名称解释:malloc的全称是memory allocation,中文叫动态内存分配。

 

2.realloc函数

原型:extern void *realloc(void *mem_address, unsigned int newsize);   

语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。   

头文件:#include <stdlib.h> 有些编译器需要#include <alloc.h>,在TC2.0中可以使用alloc.h头文件   

功能:先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。   

返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。    

注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放。

 

3.free函数

原型:extern void *realloc(void *mem_address, unsigned int newsize);   

语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。   

头文件:#include <stdlib.h> 有些编译器需要#include <alloc.h>,在TC2.0中可以使用alloc.h头文件   

功能:先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。   

返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。    

注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放。

4.calloc函数 

功 能:在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。   

跟malloc的区别:calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。   

用 法: void *calloc(unsigned n,unsigned size);   

头文件:stdlib.h或malloc.h

 

 

三、实验心得

1. 设置和修改环境变量LD_PRELOAD可用一句话实现:export LD_PRELOAD="./malloc.so"

 

2. 重载malloc后,ll、ls、cat等命令都无法使用了,会报段错误(一般是使用了未分配空间的内存);clear、pwd等命令则能正常使用。

 

3. 自定义的malloc能成功使用,不过效率比系统自带的malloc要低很多。

 

4. 要想在已赋值的字符串指针后加上新的字符串,则可用:

  sprintf(some_memory+strlen(some_memory)," Hello Fedora13!");

 

5. 所有系统自带的命令都在bin文件夹下。

 

6. 使用Ctrl+C能关闭正在运行的进程。

 

7. 自定义malloc中的free、malloc和realloc函数:

 

/* free 函数的实现*/

void free(void *firstbyte) {

struct mem_control_block *free;

free = firstbyte - sizeof(struct mem_control_block);

free->is_available = 1;

return;

}

 

/*malloc 函数的实现*/

void *malloc(size_t numbytes)
{

 void *current_location;

 struct mem_control_block *current_location_mcb;

 /* 返回内存地址初始化为0,直到找到合适的内存地址*/

 void *memory_location;

 /* 开始初始化*/

 if(! has_initialized)
 {

  malloc_init();

 }

 numbytes = numbytes + sizeof(struct mem_control_block);

 memory_location = 0;

 /* 开始查找可以使用的内存空间*/

 current_location = managed_memory_start;

 while(current_location != last_valid_address)

 {

  /* current_location 和current_location_mcb

  *指向同一个内存地址,但是, current_location_mcb 是一个结构体变量。

  *current_location 可以记录当前的内存地址*/

  current_location_mcb = (struct mem_control_block *)current_location;

  if(current_location_mcb->is_available)

  {

   if(current_location_mcb->size >= numbytes)

   {

    /* 找到了符合大小要求的内存空间*/

    current_location_mcb->is_available = 0;

    memory_location = current_location;

    break;

   }

  }

  current_location = current_location +

  current_location_mcb->size;

 }

 if(! memory_location)

 {

  sbrk(numbytes);

  memory_location = last_valid_address;

  last_valid_address = last_valid_address + numbytes;

  current_location_mcb = memory_location;

  current_location_mcb->is_available = 0;

  current_location_mcb->size = numbytes;

 }

 memory_location = memory_location + sizeof(struct

 mem_control_block);

 return memory_location;

}

 

/* realloc 函数的实现*/

void *realloc(void *first,size_t numb)

{

void *NewFirst;

if(!first)

{

  return malloc(numb);

}

else if(numb == 0)

{

  free(first);

}

else

{

  NewFirst = malloc(numb);

  if(NewFirst)

  {

     memcpy(NewFirst,first,numb);

     free(first);

     return NewFirst;

  }

}

return;

}

 

8. 内存分配的分界点是4K:小于4K,则按实际大小分配;若大于4K则在实际使用空间前,系统只会象征性的分配4K空间。这就是为什么memory2每次分配1M,但内存实际却无大变化。其最终实际只分配了256*2*4K=2M的空间,而且由于运行时间较短,所以看上去内存并没有变化。而memory3则不同,它每次只要1K,但要了一千次,按照上述原理,1K*1K=1M。所以每经过一次for循环,它会成功要到1M的内存空间!

 

9. Malloc函数给每个变量分配空间时,都会额外的建一个结构体(就类似于文件头),会有固定大小,有两个属性:是否可用、文件大小。一般的变量指针都是指向数据段的头地址,要想指到整个变量所占的空间的头地址,则需将指针减去前面结构体的大小:free = firstbyte - sizeof(struct mem_control_block);

 

 

四、实验测试代码

//memory1.c

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#define A_MEGABYTE (1024*1024)

 

int main()

{

char *some_memory;

int megabyte=A_MEGABYTE;

int exit_code=EXIT_FAILURE;

some_memory=(char *)malloc(megabyte);

if(some_memory!=NULL)

{

  sprintf(some_memory,"Hello Fedora13/n");

  printf("%s",some_memory);

  exit_code=EXIT_SUCCESS;

}

exit(exit_code);

}

 

 

 

//memory2.c

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#define ONE_M (1024*1024)

#define PHY_MEM_MEGS 256

 

int main()

{

char *some_memory;

int size_to_allocate=ONE_M;

int megs_obtained=0;

 

while(megs_obtained < (PHY_MEM_MEGS*2))

{

     some_memory=(char *)malloc(size_to_allocate);

       if(some_memory!=NULL)

    {

          megs_obtained++;

       sprintf(some_memory,"Hello Fedora13");

          printf("%s - now allocate %d Megabytes/n",some_memory,megs_obtained);

    }

    else

    {

       exit(EXIT_FAILURE);

    }    

       sleep(0.5);

}

 

exit(EXIT_SUCCESS);

}

 

 

 

 

//memory3.c

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#define ONE_K (1024)

#define MAX_MEMORY (500)

 

int main()

{

char *some_memory;

int size_to_allocate=ONE_K;

int megs_obtained=0;

int ks_obtained=0;

while(megs_obtained < MAX_MEMORY)

{

for( ks_obtained=0; ks_obtained<ONE_K; ks_obtained++)

{

   some_memory=(char *)malloc(size_to_allocate);

   if(some_memory==NULL)  exit(EXIT_FAILURE);

   sprintf(some_memory,"Hello Fedora13");

}

sleep(0.5);

megs_obtained++;

printf("%s - now allocate %d Megabytes/n",some_memory,megs_obtained);

}

exit(EXIT_SUCCESS);

}

 

 

 

//memory4.c

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#define ONE_K (1024)

#define MAX_MEMORY (30)

int main()

{

char *some_memory;

int size_to_allocate=ONE_K;

int megs_obtained=0;

int ks_obtained=0;

for( ks_obtained=0; ks_obtained<MAX_MEMORY; ks_obtained++)

{

some_memory=(char *)malloc(size_to_allocate);

if(some_memory==NULL) exit(EXIT_FAILURE);

sprintf(some_memory,"Hello World!");

sleep(0.5);

megs_obtained++;

printf("%s - now allocate %d KB/n",some_memory,megs_obtained);

 

some_memory=(char *)realloc(some_memory,size_to_allocate*2);

if(some_memory==NULL) exit(EXIT_FAILURE);

sprintf(some_memory+strlen(some_memory)," Hello Fedora13!");

//some_memory += "Hello Fedora13!";

//printf("%d/n",strlen(some_memory));

sleep(0.5);

megs_obtained += 2;

printf("%s - now allocate %d KB/n",some_memory,megs_obtained);

}

exit(EXIT_SUCCESS);

}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值