操作系统内存管理与简单分配器实现

1.操作系统的一个中心任务是内存管理,比如说I/O操作比较慢,为了让处理器尽量的忙从而提高效率,操作系统必须聪明的安排换入换出的时间以便减少内存I/O对性能的影响。

2.内存管理的五点需要:重定向,保护,共享,物理组织,逻辑组织。

3.在两级存储器间移动信息的任务应该是操作系统的任务,而这个任务恰恰是内存管理的本质所在。

4.内存分区:固定分区(产生内部碎片多),动态分区(会产生外部分区),伙伴系统。放置算法只要有首次适配,最佳适配,邻近适配。

5.内存抽象的概念:在现代的操作系统中,同一时间运行多个进程是再正常不过的了。为了解决直接操作内存带来的各种问题,引入的地址空间(Address Space),这允许每个进程拥有自己的地址。这还需要硬件上存在两个寄存器,基址寄存器(base register)和界址寄存器(limit register),第一个寄存器保存进程的开始地址,第二个寄存器保存上界,防止内存溢出。

这种情况下,任何操作虚拟地址的操作都会被转换为操作物理地址。而每一个进程所拥有的内存地址是完全不同的,因此也使得多进程成为可能。    但此时还有一个问题,通常来说,内存大小不可能容纳下所有并发执行的进程。因此,交换(Swapping)技术应运而生。这个交换和前面所讲的交换大同小异,只是现在讲的交换在多进程条件下。交换的基本思想是,将闲置的进程交换出内存,暂存在硬盘中,待执行时再交换回内存。

虚拟存储器和页的概念:虚拟内存是现代操作系统普遍使用的一种技术。前面所讲的抽象满足了多进程的要求,但很多情况下,现有内存无法满足仅仅一个大进程的内存要求(比如很多游戏,都是10G+的级别)。在早期的操作系统曾使用覆盖(overlays)来解决这个问题,将一个程序分为多个块,基本思想是先将块0加入内存,块0执行完后,将块1加入内存。依次往复,这个解决方案最大的问题是需要程序员去程序进行分块,这是一个费时费力让人痛苦不堪的过程。后来这个解决方案的(Page).每个页都是一段连续的地址。

现在操作系统解决内存使用用分页技术,进程上的叫做页,对应存储器上叫做帧,另外存储器上还保存叫做页表的数据结构,基址寄存器(页表基址寄存器,找到该进程的页表) + 页表既可以确定页的实际物理地址,即页表基址寄存器 + 虚拟页号确定物理帧,然后根据偏移量确定特定的物理地址。逻辑地址 = 页号 + 偏移量 ——(MMU)物理地址(帧号 + 偏移量)。

6.simple allocator (computer systems a promgrammer's perspective  p638)

/* a simple allocator */

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
/* private global variables */
static char *mem_start_brk;
static char *mem_brk;
static char *mem_max_addr;
static char *heap_listp;

/* basic constants and macros */
#define WSIZE 4 /* word size(bytes) */
#define DSIZE 8 /* doubleword size(bytes) */
#define CHUNKSIZE (1 << 12)
#define OVERHEAD 8
#define MAX(x, y) ((x) > (y) ? (x) : (y))
/* pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc))
/* read and write a word at addrss p */
#define GET(p) (*(size_t*)(p))
#define PUT(p, val) (*(size_t *)(p) = (val))
/*read the size and allocated fields from addrss p */
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
/* given block ptr bp, compute address of its beader and footer */
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
/* given block ptr bp , compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char*)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char*)(bp) - DSIZE)))
/*
 * mem_init initializes the memory system model
 */
static void *coalesce(void *bp);
static void *find_fit(size_t asize);
static void place(void *bp, size_t asize);
static void *extend_heap(size_t words);
void mem_init(int size)
{
mem_start_brk = (char *)malloc(size);
mem_brk = mem_start_brk;
mem_max_addr = mem_start_brk + size;
return;
}

/*
 * mem_sbrk simple model of the sbrk function.extends the heap
 * by incr bytes and returns the start address of the new area.
 * in this model ,the heap cannot be shrunk.
 */
void *mem_sbrk(int incr)
{
char *old_brk = mem_brk;
if((incr < 0) || ((mem_brk + incr) > mem_max_addr))
{
errno = ENOMEM;
return (void*)-1;
}
mem_brk += incr;
return old_brk;
}

/* hide list structure see p643 computer systems aprogrammer's perspective
 *mm_init function
 */
int mm_init(void)
{
/* create the initial empty heap */
if((heap_listp = mem_sbrk(4 * WSIZE)) == NULL)
return -1;
PUT(heap_listp, 0);
PUT(heap_listp + WSIZE, PACK(OVERHEAD, 1));
PUT(heap_listp + DSIZE, PACK(OVERHEAD, 1));
PUT(heap_listp + WSIZE + DSIZE, PACK(0, 1));
heap_listp += DSIZE;
/* extend the empty with a free block of CHUNKSIZE bytes */
if(extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
static void *extend_heap(size_t words)
{
char *bp;
size_t size;
/* allocate an even number of words to maintain alignment */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if((int)(bp = mem_sbrk(size)) < 0)
return NULL;
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(NEXT_BLKP(bp)),PACK(0, 1));
/* coalesce if the previous block was free */
return coalesce(bp);

}
void mm_free(void *bp)
{
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
static void *coalesce( void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if(prev_alloc && next_alloc)/* case 1 */
return bp;
else if (prev_alloc && !next_alloc)
{
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
return(bp);
}
else if(!prev_alloc && next_alloc)
{
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
return (PREV_BLKP(bp));
}
else
{
size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
return (PREV_BLKP(bp));
}
}
void *mm_malloc(size_t size)
{
size_t asize; /* adjust block size */
size_t extendsize; /* amount to extend heap if no fit */
char *bp;
/* ignore spurious requests */
if(size <= 0)
return NULL;
/* adjust block size to include overhead and alignment reqs */
if(size <= DSIZE)
asize = DSIZE + OVERHEAD;
else
asize = DSIZE *((size + OVERHEAD + DSIZE - 1) / DSIZE);
/* search the free list for a fit */
if(( bp = find_fit(asize)) != NULL)
{
place(bp, asize);
return bp;
}
/* NO fit found ,get more memory and place the block */
extendsize = MAX(asize, CHUNKSIZE);
if((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
static void *find_fit(size_t asize)
{
void *bp;
for(bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp))
{
if(!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp))))
{
return bp;
}
}
return NULL;/* not fit */

}
static void place(void *bp, size_t asize)
{
size_t csize = GET_SIZE(HDRP(bp));
if((csize - asize) >= (DSIZE + OVERHEAD))
{
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(csize - asize, 0));
PUT(FTRP(bp), PACK(csize - asize, 0));
}
else
{
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
}
}
int main(int argc, char **argv)
{
mm_init();
return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值