mirror of
https://github.com/cfenollosa/os-tutorial.git
synced 2024-10-27 20:34:19 +00:00
lesson 22, malloc
This commit is contained in:
parent
f98a02f6cc
commit
293f556a7e
47
22-malloc/Makefile
Normal file
47
22-malloc/Makefile
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
C_SOURCES = $(wildcard kernel/*.c drivers/*.c cpu/*.c libc/*.c)
|
||||||
|
HEADERS = $(wildcard kernel/*.h drivers/*.h cpu/*.h libc/*.h)
|
||||||
|
# Nice syntax for file extension replacement
|
||||||
|
OBJ = ${C_SOURCES:.c=.o cpu/interrupt.o}
|
||||||
|
|
||||||
|
# Change this if your cross-compiler is somewhere else
|
||||||
|
CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
|
||||||
|
GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb
|
||||||
|
# -g: Use debugging symbols in gcc
|
||||||
|
CFLAGS = -g -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs \
|
||||||
|
-Wall -Wextra -Werror
|
||||||
|
|
||||||
|
# First rule is run by default
|
||||||
|
os-image.bin: boot/bootsect.bin kernel.bin
|
||||||
|
cat $^ > os-image.bin
|
||||||
|
|
||||||
|
# '--oformat binary' deletes all symbols as a collateral, so we don't need
|
||||||
|
# to 'strip' them manually on this case
|
||||||
|
kernel.bin: boot/kernel_entry.o ${OBJ}
|
||||||
|
i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary
|
||||||
|
|
||||||
|
# Used for debugging purposes
|
||||||
|
kernel.elf: boot/kernel_entry.o ${OBJ}
|
||||||
|
i386-elf-ld -o $@ -Ttext 0x1000 $^
|
||||||
|
|
||||||
|
run: os-image.bin
|
||||||
|
qemu-system-i386 -fda os-image.bin
|
||||||
|
|
||||||
|
# Open the connection to qemu and load our kernel-object file with symbols
|
||||||
|
debug: os-image.bin kernel.elf
|
||||||
|
qemu-system-i386 -s -fda os-image.bin -d guest_errors,int &
|
||||||
|
${GDB} -ex "target remote localhost:1234" -ex "symbol-file kernel.elf"
|
||||||
|
|
||||||
|
# Generic rules for wildcards
|
||||||
|
# To make an object, always compile from its .c
|
||||||
|
%.o: %.c ${HEADERS}
|
||||||
|
${CC} ${CFLAGS} -ffreestanding -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.asm
|
||||||
|
nasm $< -f elf -o $@
|
||||||
|
|
||||||
|
%.bin: %.asm
|
||||||
|
nasm $< -f bin -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.bin *.dis *.o os-image.bin *.elf
|
||||||
|
rm -rf kernel/*.o boot/*.bin drivers/*.o boot/*.o cpu/*.o libc/*.o
|
18
22-malloc/README.md
Normal file
18
22-malloc/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
*Concepts you may want to Google beforehand: malloc*
|
||||||
|
|
||||||
|
**Goal: Implement a memory allocator**
|
||||||
|
|
||||||
|
We will add a kernel memory allocator to `libc/mem.c`. It is
|
||||||
|
implemented as a simple pointer to free memory, which keeps
|
||||||
|
growing.
|
||||||
|
|
||||||
|
The `kmalloc()` function can be used to request an aligned page,
|
||||||
|
and it will also return the real, physical address, for later use.
|
||||||
|
|
||||||
|
We'll change the `kernel.c` leaving all the "shell" code there,
|
||||||
|
Let's just try out the new `kmalloc()`, and check out that
|
||||||
|
our first page starts at 0x10000 (as hardcoded on `mem.c`) and
|
||||||
|
subsequent `kmalloc()`'s produce a new address which is
|
||||||
|
aligned 4096 bytes or 0x1000 from the previous one.
|
||||||
|
|
||||||
|
The rest of the files are unchanged from last lesson.
|
1
22-malloc/boot
Symbolic link
1
22-malloc/boot
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../21-shell/boot
|
1
22-malloc/cpu
Symbolic link
1
22-malloc/cpu
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../21-shell/cpu
|
1
22-malloc/drivers
Symbolic link
1
22-malloc/drivers
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../21-shell/drivers
|
36
22-malloc/kernel/kernel.c
Normal file
36
22-malloc/kernel/kernel.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "../cpu/isr.h"
|
||||||
|
#include "../drivers/screen.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
#include "../libc/mem.h"
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
isr_install();
|
||||||
|
irq_install();
|
||||||
|
|
||||||
|
kprint("Type something, it will go through the kernel\n"
|
||||||
|
"Type END to halt the CPU or PAGE to request a kmalloc()\n> ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_input(char *input) {
|
||||||
|
if (strcmp(input, "END") == 0) {
|
||||||
|
kprint("Stopping the CPU. Bye!\n");
|
||||||
|
asm volatile("hlt");
|
||||||
|
} else if (strcmp(input, "PAGE") == 0) {
|
||||||
|
/* Lesson 22: Code to test kmalloc, the rest is unchanged */
|
||||||
|
u32 phys_addr;
|
||||||
|
u32 page = kmalloc(1000, 1, &phys_addr);
|
||||||
|
char page_str[16];
|
||||||
|
int_to_ascii(page, page_str);
|
||||||
|
char phys_str[16];
|
||||||
|
int_to_ascii(phys_addr, phys_str);
|
||||||
|
kprint("Page: ");
|
||||||
|
kprint(page_str);
|
||||||
|
kprint(", physical address: ");
|
||||||
|
kprint(phys_str);
|
||||||
|
kprint("\n");
|
||||||
|
}
|
||||||
|
kprint("You said: ");
|
||||||
|
kprint(input);
|
||||||
|
kprint("\n> ");
|
||||||
|
}
|
6
22-malloc/kernel/kernel.h
Normal file
6
22-malloc/kernel/kernel.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef KERNEL_H
|
||||||
|
#define KERNEL_H
|
||||||
|
|
||||||
|
void user_input(char *input);
|
||||||
|
|
||||||
|
#endif
|
1
22-malloc/libc/function.h
Symbolic link
1
22-malloc/libc/function.h
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../21-shell/libc/function.h
|
33
22-malloc/libc/mem.c
Normal file
33
22-malloc/libc/mem.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
void memory_copy(u8 *source, u8 *dest, int nbytes) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nbytes; i++) {
|
||||||
|
*(dest + i) = *(source + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_set(u8 *dest, u8 val, u32 len) {
|
||||||
|
u8 *temp = (u8 *)dest;
|
||||||
|
for ( ; len != 0; len--) *temp++ = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should be computed at link time, but a hardcoded
|
||||||
|
* value is fine for now. Remember that our kernel starts
|
||||||
|
* at 0x1000 as defined on the Makefile */
|
||||||
|
u32 free_mem_addr = 0x10000;
|
||||||
|
/* Implementation is just a pointer to some free memory which
|
||||||
|
* keeps growing */
|
||||||
|
u32 kmalloc(u32 size, int align, u32 *phys_addr) {
|
||||||
|
/* Pages are aligned to 4K, or 0x1000 */
|
||||||
|
if (align == 1 && (free_mem_addr & 0xFFFFF000)) {
|
||||||
|
free_mem_addr &= 0xFFFFF000;
|
||||||
|
free_mem_addr += 0x1000;
|
||||||
|
}
|
||||||
|
/* Save also the physical address */
|
||||||
|
if (phys_addr) *phys_addr = free_mem_addr;
|
||||||
|
|
||||||
|
u32 ret = free_mem_addr;
|
||||||
|
free_mem_addr += size; /* Remember to increment the pointer */
|
||||||
|
return ret;
|
||||||
|
}
|
12
22-malloc/libc/mem.h
Normal file
12
22-malloc/libc/mem.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef MEM_H
|
||||||
|
#define MEM_H
|
||||||
|
|
||||||
|
#include "../cpu/types.h"
|
||||||
|
|
||||||
|
void memory_copy(u8 *source, u8 *dest, int nbytes);
|
||||||
|
void memory_set(u8 *dest, u8 val, u32 len);
|
||||||
|
|
||||||
|
/* At this stage there is no 'free' implemented. */
|
||||||
|
u32 kmalloc(u32 size, int align, u32 *phys_addr);
|
||||||
|
|
||||||
|
#endif
|
1
22-malloc/libc/string.c
Symbolic link
1
22-malloc/libc/string.c
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../21-shell/libc/string.c
|
1
22-malloc/libc/string.h
Symbolic link
1
22-malloc/libc/string.h
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../21-shell/libc/string.h
|
Loading…
Reference in New Issue
Block a user