Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- 다익스트라 알고리즘(Dijkstra Algorithm)
- 그래프(Graph)
- 알고리즘 개념
- 플로이드 워셜 알고리즘(Floyd-Warshall Algorithm)
- 백준 2261번
- 백준 10000번
- DFS(Depth First Search)
- 이분 그래프(Bipartite Graph)
- 스택(Stack)
- 백준 21606번
- 백준 1707번
- 분할 정복(Divide and Conquer)
- BFS
- 백준 1948번
- 백준 2504번
- 이분 탐색(Binary Search)
- 백준 17608번
- BFS(Breadth First Search)
- 동적 프로그래밍(Dynamic Programming)
- 위상 정렬(Topological Sort)
- 백준 2812번
- 위상 정렬(Topology Sort)
- DFS & BFS
- DFS
- 백준 18352번
- 그리디 알고리즘(Greedy Algorithm)
- 백준 9012번
- 백준 2493번
- 큐(Queue)
- 트리(Tree)
Archives
- Today
- Total
Always Be Wise
동적 메모리 할당 - malloc 함수 구현(명시적 가용 리스트 이용) 본문
728x90
명시적 가용 리스트
묵시적 가용 리스트는 할당 시간이 전체 힙 블록의 수에 비례한다. 그런데 사용 가능한 블록들을 일종의 명시적 자료구조로 구성하면
할당 시간을 전체 힙 블록의 수가 아닌 사용 가능한 블록의 수에 비례하게 줄일 수 있다. 예를 들어 아래와 같이 사용 가능한 블록내에
pred(predecessor)와 succ(successor) 포인터를 포함하는 이중 연결 리스트로 구성할 수 있다.
그런데 할당 시간과 별개로 반환 시간은 사용 가능한 리스트 내에서 블록 정렬 정책을 어떻게 선택하느냐에 따라 블록의 수에
비례하거나 상수 시간을 가질 수 있다. 우선, 가용 블록 리스트를 주소 순으로 관리하는 경우, 리스트 내 각 블록의 주소는 다음 블록의
주소보다 작다. 이 경우, 적당한 블록을 리스트에서 찾는데 선형 검색 시간을 필요로 한다. 다른 접근법은 반환된 블록들을 리스트의
시작 부분에 삽입해서 리스트를 후입선출(LIFO, Last In First Out) 순으로 유지하는 것이다. 이 경우 반환은 상수 시간에 수행된다.
명시적 리스트의 단점은 가용 블록에 헤더와 풋터 뿐만 아니라 포인터들을 포함해야 한다는 점에서 최소 블록 크기가 커져 잠재적인
내부 단편화 가능성이 증가한다는 것이다.
▶ 구현 코드(First Fit)
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
team_t team = {
/* Team name */
"jungle3rd_week06",
/* First member's full name */
"group_09",
/* First member's email address */
"bewise.seunghyun@gmail.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""};
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Basic constants and macros */
#define WSIZE 4 // Word and header/footer size (bytes)
#define DSIZE 8 // Double word size (bytes)
#define CHUNKSIZE (1 << 12) // Extend heap by this amount (bytes)
#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 address p */
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
/* Given block ptr bp, compute address of its header 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)))
#define PREC_FREEP(bp) (*(void **)(bp)) // *(GET(PREC_FREEP(bp))) == 다음 가용리스트의 bp //Predecessor
#define SUCC_FREEP(bp) (*(void **)(bp + WSIZE)) // *(GET(SUCC_FREEP(bp))) == 다음 가용리스트의 bp //successor
/* glbal variable */
static void *heap_listp; // 정적 전역변수를 사용한 할당기
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *find_fit(size_t asize);
static void place(void *bp, size_t asize);
void removeBlock(void *bp);
void putFreeBlock(void *bp);
static void *free_listp; // free block들의 시작점을 나타내는 포인터
/* mm_init - initialize the malloc package. */
int mm_init(void){
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(6 * WSIZE)) == (void *) - 1)
return -1;
PUT(heap_listp, 0);
PUT(heap_listp + (1 * WSIZE), PACK(16, 1));
PUT(heap_listp + (2 * WSIZE), NULL);
PUT(heap_listp + (3 * WSIZE), NULL);
PUT(heap_listp + (4 * WSIZE), PACK(16, 1));
PUT(heap_listp + (5 * WSIZE), PACK(0, 1));
// free_listp 초기화
free_listp = heap_listp + DSIZE; // 가용리스트에 블록이 추가될 때 마다 항상 리스트의 제일 앞에 추가될 것이므로 지금 생성한 프롤로그 블록은 항상 가용리스트의 끝에 위치하게 된다.
if (extend_heap(CHUNKSIZE / DSIZE) == NULL){
return -1;
}
return 0;
}
//항상 가용리스트 맨 뒤에 프롤로그 블록이 존재하고 있기 때문에 조건을 간소화할 수 있다.
void removeBlock(void *bp)
{
// 첫번째 블럭을 없앨 때
if (bp == free_listp)
{
PREC_FREEP(SUCC_FREEP(bp)) = NULL;
free_listp = SUCC_FREEP(bp);
// 앞 뒤 모두 있을 때
}
else
{
SUCC_FREEP(PREC_FREEP(bp)) = SUCC_FREEP(bp);
PREC_FREEP(SUCC_FREEP(bp)) = PREC_FREEP(bp);
}
}
//새로 반환되거나 생성된 가용 블록을 가용리스트 맨 앞에 추가한다.
void putFreeBlock(void *bp)
{
SUCC_FREEP(bp) = free_listp;
PREC_FREEP(bp) = NULL;
PREC_FREEP(free_listp) = bp;
free_listp = bp;
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(HDRP(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)
{
removeBlock(NEXT_BLKP(bp));
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (!prev_alloc && next_alloc)
{
removeBlock(PREV_BLKP(bp));
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
bp = PREV_BLKP(bp);
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (!prev_alloc && !next_alloc)
{
removeBlock(PREV_BLKP(bp));
removeBlock(NEXT_BLKP(bp));
size += GET_SIZE(HDRP(NEXT_BLKP(bp))) + GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
//연결된 블록을 가용리스트에 추가
putFreeBlock(bp);
return bp;
}
static void *extend_heap(size_t words)
{
size_t size;
char *bp;
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if (size < 24) {
size = 24;
}
if ((long)(bp = mem_sbrk(size)) == -1) {
return NULL;
}
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
return coalesce(bp);
}
static void *find_fit(size_t asize)
{
// first fit
void *bp;
bp = free_listp;
//가용리스트 내부의 유일한 할당 블록은 맨 뒤의 프롤로그 블록이므로 할당 블록을 만나면 for문을 종료한다.
for (bp; GET_ALLOC(HDRP(bp)) != 1; bp = SUCC_FREEP(bp)){
if (GET_SIZE(HDRP(bp)) >= asize)
{
return bp;
}
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t csize;
csize = GET_SIZE(HDRP(bp));
// 할당될 블록이니 가용리스트 내부에서 제거해준다.
removeBlock(bp);
if (csize - asize >= 16)
{
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));
// 가용리스트 첫번째에 분할된 블럭을 넣는다.
putFreeBlock(bp);
}
else
{
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
}
}
/* mm_malloc - Allocate a block by incrementing the brk pointer. Always allocate a block whose size is a multiple of the alignment. */
void *mm_malloc(size_t size){
size_t asize;
size_t extendsize;
void *bp;
if (size == 0)
return NULL;
if (size <= DSIZE){
asize = 2 * DSIZE;
}
else{
asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);
}
if ((bp = find_fit(asize)) != NULL){
place(bp, asize);
return bp;
}
extendsize = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extendsize / WSIZE)) == NULL) {
return NULL;
}
place(bp, asize);
return 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);
}
void *mm_realloc(void *bp, size_t size)
{
if (size <= 0)
{
mm_free(bp);
return 0;
}
if (bp == NULL)
{
return mm_malloc(size);
}
void *newp = mm_malloc(size);
if (newp == NULL)
{
return 0;
}
size_t oldsize = GET_SIZE(HDRP(bp));
if (size < oldsize)
{
oldsize = size;
}
memcpy(newp, bp, oldsize);
mm_free(bp);
return newp;
}
'컴퓨터 시스템 > CSAPP' 카테고리의 다른 글
네트워크 프로그래밍 (0) | 2021.12.16 |
---|---|
동적 메모리 할당 - malloc 함수 구현(분리 가용 리스트) (0) | 2021.12.15 |
동적 메모리 할당 - malloc 함수 구현(묵시적 가용 리스트 이용) (0) | 2021.12.13 |
가상 메모리 (0) | 2021.12.10 |
동적 메모리 할당과 할당기 (0) | 2021.12.09 |
Comments