diff --git a/README.md b/README.md index 8c5cb43bb6dcd1afd945beaf7482ad3e2c5b64e2..86be9a3e5f9f5bd5d76b036ada6bf450bbc3abb6 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,77 @@ -Operating system Assignment 4 -=================== +# Operating system Assignment 4 + +## TA Info & Assignment URL -TA Info & Assignment URL --- - TA Mail: ckai22@ajou.ac.kr -- TA gitlab: http://git.ajou.ac.kr/ckai22 +- TA gitlab: <http://git.ajou.ac.kr/ckai22> + +## File Info -File Info --- + - **main.c**: Implements input and output - **alloc.h**: Implements meta structure - **alloc.c**: Implements malloc, free, and realloc -- **Makefile**: compiles the +- **Makefile**: compiles the - **input** directory: saves the input file -TEST +## TEST + --- -##### Test proceeds as follows. -- - - -1. Input File name to the main function parameter. -2. Read File (File IO) -3. Interpret commands in File -4. Output to stdout - -##### **Command structure in File** -- - - -"Number of command lines" "Fit"<br> -"Command" "Contents"<br> -"Command" "Contents"<br> -...<br> - -##### **Fit type (case sensitive)** -- - - -F: first fit<br> -B: Best fit<br> -W: worst fit<br> - -##### **Command type** -- - - -**s** String: String The command to put the value into<br> -**f** n: nth allocation area free<br> -**r** n m: reallocation with m bytes in the nth allocation area<br> -**e** n: Allocate space without contents to n bytes<br> - -##### **Output** -- - - -“Free" "size" "content (if command is m only)"<br> -"Free" "size" "content (if command is m only)"<br> -...<br> - -##### **Example** -- - - -E1)<br> -**Input**<br> -3 F<br> -m Think like a man of action and act like man of thought.<br> -m Courage is very important. Like a muscle, it is strengthened by use.<br> -m Life is the art of drawing sufficient conclusions from insufficient premises.<br> -**Output**<br> -0 56 Think like a man of action and act like man of thought.<br> -0 72 Courage is very important. Like a muscle, it is strengthened by use.<br> -0 80 Life is the art of drawing sufficient conclusions from insufficient premises.<br> -<br> -E2)<br> -**Input**<br> -2 F<br> -m Think like a man of action and act like man of thought.<br> -f 0<br> -**Output**<br> -1 56 +### **Test proceeds as follows** + +1. Input File name to the main function parameter. +2. Read File (File IO) +3. Interpret commands in File +4. Output to stdout + +### **Command structure in File** + +"Number of command lines" "Fit" +"Command" "Contents" +"Command" "Contents" +... + +### **Fit type (case sensitive)** + +F: first fit +B: Best fit +W: worst fit + +### **Command type** + +**s** String: String The command to put the value into +**f** n: nth allocation area free +**r** n m: reallocation with m bytes in the nth allocation area +**e** n: Allocate space without contents to n bytes + +### **Output** + +“Free" "size" "content (if command is m only)" +"Free" "size" "content (if command is m only)" +... + +### **Example** + +E1) +**Input** +3 F +m Think like a man of action and act like man of thought. +m Courage is very important. Like a muscle, it is strengthened by use. +m Life is the art of drawing sufficient conclusions from insufficient premises. +**Output** +0 56 Think like a man of action and act like man of thought. +0 72 Courage is very important. Like a muscle, it is strengthened by use. +0 80 Life is the art of drawing sufficient conclusions from insufficient premises. + +E2) +**Input** +2 F +m Think like a man of action and act like man of thought. +f 0 +**Output** +1 56 \ No newline at end of file diff --git a/alloc.c b/alloc.c index 931b9fd59da6368f6a48cfa9f681133f918b162b..d6528bb6138a13b2265b362839d8a8eab7b9f0a7 100644 --- a/alloc.c +++ b/alloc.c @@ -1 +1,207 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <limits.h> #include "alloc.h" +#define align(n) (((n+3)/4)*4) +meta *base; +meta *last; + +void *m_find(size_t size) +{ + if(!base) return 0; + //else if(base==last) return base+1; + + meta *cur=base, *ans=0; + size_t max=0, min=SIZE_T_MAX; + bool find=false; + + do + { + switch(fit_type) + { + case FIRST_FIT: + if(cur->free && cur->size>=size) find=true; + break; + + case BEST_FIT: + if(cur->free && cur->size>=size && cur->size<min) + { + ans=cur; + min=ans->size; + } + break; + + case WORST_FIT: + if(cur->free && cur->size>=size && cur->size>max) + { + ans=cur; + max=ans->size; + } + break; + } + if(!find) cur=cur->next; + } while(cur && !find); + + if(find) ans=cur; + + return !ans?ans:ans+1; +} + +void *m_merge(meta *cur1, meta *cur2) +{ + cur1->next=cur2->next; + cur1->size+=(cur2->size+META_SIZE); + if(cur2->next && cur2->next->free) + m_merge(cur1, cur2->next); + else if(cur1->prev && cur1->prev->free) + cur1=(m_merge(cur1->prev, cur1)-META_SIZE); + return cur1+1; +} + +void *m_split(meta *cur, size_t size) +{ + if(cur->size<=size) return cur+1; + + size_t size_sum=size+META_SIZE; + meta *new_meta=(void *)cur+size_sum; + new_meta->prev=cur; + new_meta->next=cur->next; + new_meta->free=true; + new_meta->size=cur->size-size_sum; + + cur->size=size; + cur->next=new_meta; + return cur+1; +} + +void *m_malloc(size_t size) +{ + size=align(size); + size_t size_sum=size+META_SIZE; + void *result; + + if(!base) + { + //if(sbrk(0)==-1) return; + base=sbrk(0); + sbrk((int)size_sum); + base->free=true; + base->size=size; + last=base; + } + + result=m_find(size); + + //if no result + if(!result) + { + if(last->free && (last->size < size)) + size_sum=size-last->size; + meta *result_meta=last; + last=sbrk((int)size_sum); + last->prev=result_meta; + last->free=true; + last->size=size; + result_meta->next=last; + result=result_meta+1; + + //realloc for the merging case + if(last->free && (last->size < size)) + result=m_realloc(result, size); + else + result=last+1; + } + result=m_split(result-META_SIZE, size); + + return result; +} + +void *m_realloc(void *ptr, size_t size) +{ + size=align(size); + void *cur=ptr; + meta *cur_meta=cur-META_SIZE; + + if(cur_meta->size==size) return ptr; + //TODO: case when extra size is sufficient + if(cur_meta->size>size) + cur=m_split(cur_meta, size); + else if(cur_meta->next && cur_meta->next->free && cur_meta->size+cur_meta->next->size+META_SIZE > size) + { + m_free(ptr); + cur=m_merge(cur_meta, cur_meta->next); + cur_meta=cur-META_SIZE; + if(cur_meta->size+META_SIZE > size) + cur=m_split(cur_meta, size); + } + //nothing to merge or split + else + { + cur=m_malloc(size); + cur_meta=cur-META_SIZE; + memcpy(cur, ptr, size); + cur_meta->free=false; + m_free(ptr); + } + + return cur; +} + +void m_free(void *ptr) +{ + //if(!ptr) return 0; + + meta *cur=ptr-META_SIZE; + cur->free=true; + + if(cur->prev && cur->prev->free) + cur=m_merge(cur->prev,cur); + else if(cur->next && cur->next->free) + cur=m_merge(cur,cur->next); + + //release memory on the last block + if(cur->prev && cur==last) + { + last=last->prev; + last->next=NULL; + } + + //back to origin state if there are no blocks + else if(!cur->prev && cur==last) + base=last=NULL; + //return 1; +} + +void *m_travel(int idx) +{ + if(!base) return 0; + meta *cur=base; + for(int i=0;cur && i<idx;i++) + cur=cur->next; + + if(!cur) return 0; + else return cur+1; +} + +void print_mem(void) +{ + /* + if(!base) + { + fprintf(stdout, "No memory allocated!\n"); + return; + } + */ + + meta *cur=base; + while(cur) + { + fprintf(stdout, "%d %zu", cur->free, cur->size); + if(!cur->free) fprintf(stdout, " %s", (char *)(cur+1)); + fprintf(stdout, "\n"); + cur=cur->next; + } + + return; +} diff --git a/alloc.h b/alloc.h index 3245f55c3496bc75c70c04625ca3dcb7dd5d0afd..acba4047f19a05f25d3f7d1ac2fb52cfac946ed9 100644 --- a/alloc.h +++ b/alloc.h @@ -1,8 +1,28 @@ +#include <stdio.h> +#include <stdbool.h> #ifndef _ALLOC_H_ #define _ALLOC_H_ +#define FIRST_FIT 'F' +#define BEST_FIT 'B' +#define WORST_FIT 'W' +#define META_SIZE sizeof(struct meta_struct) typedef struct meta_struct { - + struct meta_struct *prev; + struct meta_struct *next; + bool free; + size_t size; } meta; +extern int fit_type; + +void *m_find(size_t size); +void *m_merge(meta *cur1, meta *cur2); +void *m_split(meta *cur, size_t size); +void *m_malloc(size_t size); +void *m_realloc(void *ptr, size_t size); +void m_free(void *ptr); +void *m_travel(int idx); +void print_mem(void); + #endif diff --git a/main.c b/main.c index b5fba0682b01a1005462aa24bf4ac2f21227e156..646319f2097ae46d238378875c98e9fd290b3d2e 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,71 @@ +#include <stdio.h> +#include <string.h> #include "alloc.h" +#define BUF_MAX 1000 +#define FILE_PATH "test1.txt" +#define STRING 's' +#define FREE 'f' +#define REALLOC 'r' +#define ALLOC 'e' +char buf[BUF_MAX+10]; +void *ptr; +int fit_type; int main() { + FILE *fp=fopen(FILE_PATH, "rt"); + if(!fp) + { + printf("Cannot open file!\n"); + return 0; + } + + char cmd; + int cmd_num, idx; + size_t size_alloc; + fscanf(fp, "%d %c\n", &cmd_num, &fit_type); + for(int i=0;i<cmd_num;i++) + { + fscanf(fp, "%c ", &cmd); + switch(cmd) + { + case STRING: + fgets(buf, BUF_MAX, fp); + size_alloc=strlen(buf); + buf[size_alloc-1]='\0'; + ptr=m_malloc(size_alloc); + strcpy(ptr, buf); + meta *tmp=ptr-META_SIZE; + tmp->free=false; + //(meta *)(ptr-META_SIZE)->free=false; + break; + + case FREE: + fscanf(fp, "%d\n", &idx); + ptr=m_travel(idx); + + if(!ptr){} + //fprintf(stdout, "No allocation on block %d\n", idx); + else m_free(ptr); + break; + + case REALLOC: + fscanf(fp, "%d %zd\n", &idx, &size_alloc); + ptr=m_realloc(m_travel(idx), size_alloc); + break; + + case ALLOC: + fscanf(fp, "%zd\n", &size_alloc); + ptr=m_malloc(size_alloc); + break; + + default: + fprintf(stdout, "Wrong command\n"); + } + } + + print_mem(); + + fclose(fp); return 0; }