您的位置:首页 > 其它

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

2013-05-09 22:18 344 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐