sistema de gerenciamento de memória

Prefácio

O blog registra a operação do experimento no Capítulo 8 de "Operating System Truth Restore" ~

Ambiente experimental: ubuntu18.04+VMware, baixe e instale Bochs

Conteúdo do experimento:

  1. Implementar asserção de afirmação.
  2. Implemente funções de manipulação de strings. (memset, memcpy, strcpy, strlen, strchr, etc.)
  3. Implemente bitmaps para gerenciamento de memória.
  4. Implementa as partes básicas do sistema de gerenciamento de memória.
  5. Implemente alocação de memória simples com base no Experimento 4.

conhecimento pré-requisito

arquivo make

Entendimento do Makefile

Definição Makefile: Este arquivo descreve o relacionamento entre os vários arquivos do programa e fornece comandos de atualização para cada arquivo.

Ao executar o comando make, um makefile é necessário para informar ao comando make como compilar e vincular o programa.

gramática básica

A sintaxe básica do makefile consiste em três partes

目标文件:依赖文件
[Tab]命令
  1. O arquivo de destino refere-se ao arquivo que você deseja gerar nesta regra. Pode ser um arquivo de destino terminando em .o, um arquivo executável ou um pseudo-alvo.
  2. Arquivos dependentes referem-se a quais arquivos são necessários para gerar os arquivos de destino nesta regra.
  3. Um comando é uma ação a ser executada nesta regra. [Deve começar com Tab no início da linha]

[Suplemento 1] makeComo o programa determina que os arquivos precisam ser atualizados?

No Linux, os arquivos são divididos em duas partes: atributos e dados.Cada arquivo possui três tempos ( statvisíveis com comandos). O programa make obtém o mtime (tempo de modificação) do arquivo dependente e do arquivo de destino, respectivamente, e compara se o mtime do arquivo dependente é mais recente que o mtime do arquivo de destino, para determinar se o comando na regra deve ser executado.

makefileO nome do arquivo do [Suplemento 2] foi corrigido?

makefileO nome do arquivo não é fixo e pode ser especificado com o parâmetro -f ao executar o make. Se -f não for especificado, por padrão, o make procurará primeiro por um arquivo chamado GNUmakefile. Se o arquivo não existir, então ele procurará por um arquivo chamado makefile. Se o makefile não existir, ele finalmente procurará por um arquivo chamado Makefile.document.

(Para operações detalhadas do makefile, consulte o livro original ou a documentação oficial do Baidu)

bitmap

O Experimento 3 utilizou esse conhecimento.

Bitmap: Bitmap usa 1 bit em um byte para mapear recursos de outros tamanhos de unidade. A essência é o mapeamento.

O sistema operacional pode usar bitmaps para gerenciamento de memória (conforme mostrado na figura abaixo). Se um bitmap for usado para gerenciar a memória, cada bit no bitmap representará 4 KB na memória física real, que é uma página. Ou seja, um bit no bitmap corresponde a uma página na memória física. Se um bit for 0 , Indica que a página correspondente a este bit não está alocada e disponível. Caso contrário, não poderá ser redistribuído temporariamente.

Insira a descrição da imagem aqui

Planejamento de pool de memória

O espaço de memória ocupado pelos programas do usuário é alocado pelo sistema operacional.

No modo protegido, o endereço do programa torna-se um endereço virtual e o endereço físico correspondente ao endereço virtual é mapeado pelo mecanismo de paginação.

Como existem endereços virtuais e endereços físicos no mecanismo de paginação, o gerenciamento é mais fácil, por isso criamos um pool de endereços de memória virtual e um pool de endereços de memória física .

Primeiro, vamos descrever o planejamento do pool de memória física (o diagrama esquemático é mostrado abaixo).

Divisão de conjuntos de memória física:

  • Parte dela é utilizada apenas para rodar o kernel, ou seja, a memória física desse pool de memória é utilizada apenas pelo sistema operacional. Esta parte é chamada de pool de memória física do kernel.
  • A outra parte é utilizada apenas para executar processos de usuário, ou seja, a memória física deste pool de memória é alocada apenas para processos de usuário. Esta parte é chamada de pool de memória física do usuário.

A memória no pool de memória é obtida em unidades de páginas, sendo que uma página tem 4 KB.

Insira a descrição da imagem aqui
Ou seja, a memória física é dividida em dois conjuntos de memória.

Conjunto de endereços de memória virtual (diagrama esquemático a seguir)

  • Kernel: Aqui, deixamos o kernel solicitar memória por meio do sistema de gerenciamento de memória. Para isso, possui um pool de endereços virtuais. Quando se aplica à memória, ele aloca um endereço virtual do próprio pool de endereços virtuais do kernel, depois aloca memória física do pool de memória física do kernel (específico do kernel) e, finalmente, estabelece um relacionamento de mapeamento entre os dois endereços na própria página do kernel mesa.
  • Processo do usuário: para um processo do usuário, quando se aplica à memória do sistema de gerenciamento de memória, ou seja, do sistema operacional, o sistema operacional primeiro aloca endereços virtuais livres do próprio pool de endereços virtuais do processo do usuário e, em seguida, aloca endereços virtuais livres de o pool de memória física do usuário (todos os usuários alocam memória física livre no processo compartilhado) e, em seguida, estabelecem um relacionamento de mapeamento entre os dois endereços na tabela de páginas do próprio processo do usuário.

Insira a descrição da imagem aqui

Operação experimental

experimente um

Este experimento implementa afirmação assertiva

(base) user@ubuntu:/home/cooiboi/bochs/kernel$ sudo vim debug.c
(base) user@ubuntu:/home/cooiboi/bochs/kernel$ sudo vim debug.h
(base) user@ubuntu:/home/cooiboi/bochs/kernel$ sudo vim interrupt.c
(base) user@ubuntu:/home/cooiboi/bochs/kernel$ sudo vim interrupt.h
(base) user@ubuntu:/home/cooiboi/bochs/kernel$ sudo vim  main.c

Escreva um makefile (observe o caminho do arquivo do seu computador)

(base) user@ubuntu:/home/cooiboi/bochs$ sudo vim makefile
BUILD_DIR = ./build
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/ 
ASFLAGS = -f elf
CFLAGS = -Wall -m32 -fno-stack-protector $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS =  -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \
      $(BUILD_DIR)/debug.o 

##############     c代码编译     			###############
##############     后面的代码以后照本宣科即可		###############
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h lib/kernel/print.h \
        lib/stdint.h kernel/interrupt.h device/timer.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \
        lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/timer.c device/timer.h lib/stdint.h\
        lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \
        lib/kernel/print.h lib/stdint.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@


##############    汇编代码编译    ###############
$(BUILD_DIR)/kernel.o: kernel/kernel.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/print.o: lib/kernel/print.S
	$(AS) $(ASFLAGS) $< -o $@

##############    链接所有目标文件    #############
$(BUILD_DIR)/kernel.bin: $(OBJS)
	$(LD) $(LDFLAGS) $^ -o $@

.PHONY : mk_dir hd clean all

mk_dir:
	if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi

hd:
	dd if=$(BUILD_DIR)/kernel.bin \
           of=/home/cooiboi/bochs/boot/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc

clean:
	cd $(BUILD_DIR) && rm -f  ./*

build: $(BUILD_DIR)/kernel.bin

all: mk_dir build hd

Entre no modo root primeiro, caso contrário, apareceráPermission denied

(base) user@ubuntu:/home/cooiboi/bochs$ su
Password: 

executar make allcomando

root@ubuntu:/home/cooiboi/bochs# make all
if [ ! -d ./build ]; then mkdir ./build; fi
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes kernel/init.c -o build/init.o
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes kernel/interrupt.c -o build/interrupt.o
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes kernel/debug.c -o build/debug.o
ld -m elf_i386 -Ttext 0xc0001500 -e main -Map ./build/kernel.map build/main.o build/init.o build/interrupt.o build/timer.o build/kernel.o build/print.o build/debug.o -o build/kernel.bin
dd if=./build/kernel.bin \
           of=/home/cooiboi/bochs/boot/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc
22+1 records in
22+1 records out
11732 bytes (12 kB, 11 KiB) copied, 0.000227052 s, 51.7 MB/s

Iniciar Bochs

sudo bin/bochs -f boot/bochsrc.disk

Insira a descrição da imagem aqui

Experimento 2

Este experimento implementa funções relacionadas a strings

Por exemplo memset, memcpy, strcpy, strlen, strchr, etc.

Crie string.c e string.h em lib

root@ubuntu:/home/cooiboi/bochs/lib# sudo vim string.c
root@ubuntu:/home/cooiboi/bochs/lib# sudo vim string.h
root@ubuntu:/home/cooiboi/bochs/lib# ls
kernel  stdint.h  string.c  string.h  user

Modifique main.c para gerar Hello OSa operação de afirmação de comprimento e comparação

root@ubuntu:/home/cooiboi/bochs/kernel# sudo vim  main.c
#include "print.h"
#include "init.h"
#include "debug.h"
#include "string.h"

int main(void) {
    
    
   put_str("I am kernel\n");
   init_all();
   put_str("length:");
   put_int(strlen("Hello OS"));
   ASSERT(strcmp("bbb","bbb"));
   while(1);
}

Modifique o arquivo makefile, um total de 3 modificações

OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \
      $(BUILD_DIR)/debug.o $(BUILD_DIR)/string.o 
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h lib/string.h
	$(CC) $(CFLAGS) $< -o $@     
$(BUILD_DIR)/string.o: lib/string.c lib/string.h \
        lib/stdint.h  kernel/debug.h  lib/string.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@

Makefile completo

BUILD_DIR = ./build
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/ 
ASFLAGS = -f elf
CFLAGS = -Wall -m32 -fno-stack-protector $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS =  -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \
      $(BUILD_DIR)/debug.o $(BUILD_DIR)/string.o 

##############     c代码编译     			###############
##############     后面的代码以后照本宣科即可		###############
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h lib/string.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h lib/kernel/print.h \
        lib/stdint.h kernel/interrupt.h device/timer.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \
        lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/timer.c device/timer.h lib/stdint.h\
        lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \
        lib/kernel/print.h lib/stdint.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/string.o: lib/string.c lib/string.h \
        lib/stdint.h  kernel/debug.h  lib/string.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@

##############    汇编代码编译    ###############
$(BUILD_DIR)/kernel.o: kernel/kernel.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/print.o: lib/kernel/print.S
	$(AS) $(ASFLAGS) $< -o $@

##############    链接所有目标文件    #############
$(BUILD_DIR)/kernel.bin: $(OBJS)
	$(LD) $(LDFLAGS) $^ -o $@

.PHONY : mk_dir hd clean all

mk_dir:
	if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi

hd:
	dd if=$(BUILD_DIR)/kernel.bin \
           of=/home/cooiboi/bochs/boot/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc

clean:
	cd $(BUILD_DIR) && rm -f  ./*

build: $(BUILD_DIR)/kernel.bin

all: mk_dir build hd
make all
root@ubuntu:/home/cooiboi/bochs# make all
if [ ! -d ./build ]; then mkdir ./build; fi
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes kernel/main.c -o build/main.o
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes lib/string.c -o build/string.o
ld -m elf_i386 -Ttext 0xc0001500 -e main -Map ./build/kernel.map build/main.o build/init.o build/interrupt.o build/timer.o build/kernel.o build/print.o build/debug.o build/string.o -o build/kernel.bin
dd if=./build/kernel.bin \
           of=/home/cooiboi/bochs/boot/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc
23+1 records in
23+1 records out
12284 bytes (12 kB, 12 KiB) copied, 0.000235485 s, 52.2 MB/s

ERRO: NULL não está definido

root@ubuntu:/home/cooiboi/bochs# sudo make all
if [ ! -d ./build ]; then mkdir ./build; fi
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes lib/string.c -o build/string.o
In file included from lib/string.c:3:0:
lib/string.c: In function ‘memset’:
lib/string.c:7:19: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(dst_ != NULL);
                   ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c:7:19: note: each undeclared identifier is reported only once for each function it appears in
    ASSERT(dst_ != NULL);
                   ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘memcpy’:
lib/string.c:15:19: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(dst_ != NULL && src_ != NULL);
                   ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘memcmp’:
lib/string.c:26:16: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(a != NULL || b != NULL);
                ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strcpy’:
lib/string.c:39:19: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(dst_ != NULL && src_ != NULL);
                   ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strlen’:
lib/string.c:47:18: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(str != NULL);
                  ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strcmp’:
lib/string.c:55:16: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(a != NULL && b != NULL);
                ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strchr’:
lib/string.c:67:18: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(str != NULL);
                  ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strrchr’:
lib/string.c:79:18: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(str != NULL);
                  ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strcat’:
lib/string.c:93:19: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(dst_ != NULL && src_ != NULL);
                   ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strchrs’:
lib/string.c:103:18: error: ‘NULL’ undeclared (first use in this function)
    ASSERT(str != NULL);
                  ^
kernel/debug.h:16:11: note: in definition of macro ‘ASSERT’
       if (CONDITION) {
    
    } else {
    
                                        \
           ^
lib/string.c: In function ‘strchr’:
lib/string.c:75:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
makefile:38: recipe for target 'build/string.o' failed
make: *** [build/string.o] Error 1

Solução :

Adicione o arquivo lib/string.h#define NULL 0

Insira a descrição da imagem aqui


Iniciar Bochs

sudo bin/bochs -f boot/bochsrc.disk
root@ubuntu:/home/cooiboi/bochs# sudo bin/bochs -f boot/bochsrc.disk

Insira a descrição da imagem aqui

Experimento 3

Implemente bitmaps para gerenciamento de memória.

Crie arquivos bitmap.c e bitmap.h no diretório lib/kernel.

root@ubuntu:/home/cooiboi/bochs/lib/kernel# sudo vim bitmap.c
root@ubuntu:/home/cooiboi/bochs/lib/kernel# sudo vim bitmap.h

lib/kernel/bitmap.h

Insira a descrição da imagem aqui
struct bitmap define duas variáveis ​​de membro: bits de ponteiro de bitmap e comprimento de byte de bitmap btmp_bytes_len.

Experimento 4

Implementar a parte básica do sistema de gerenciamento de memória

(Há um problema com esta parte do código, você pode pular diretamente e ir para o próximo experimento)

Crie os arquivos memory.c e memory.h no diretório do kernel.

root@ubuntu:/home/cooiboi/bochs/kernel# vim memory.c
root@ubuntu:/home/cooiboi/bochs/kernel# vim memory.h

Adicionado um #include "memory.h" e um mem_init(); em /kernel/init.c.

root@ubuntu:/home/cooiboi/bochs/kernel# vim init.c

Modifique o arquivo makefile, modifique 3 lugares

OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \
      $(BUILD_DIR)/debug.o $(BUILD_DIR)/string.o $(BUILD_DIR)/memory.o
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h lib/string.h kernel/memory.h
        $(CC) $(CFLAGS) $< -o $@
$(BUILD_DIR)/memory.o: kernel/memory.c kernel/memory.h lib/stdint.h lib/kernel/bitmap.h \
   	kernel/global.h kernel/global.h kernel/debug.h lib/kernel/print.h \
	lib/kernel/io.h kernel/interrupt.h lib/string.h lib/stdint.h
	$(CC) $(CFLAGS) $< -o $@

bitmap.h

Precisa adicionar

typedef int bool;
root@ubuntu:/home/cooiboi/bochs# make all
if [ ! -d ./build ]; then mkdir ./build; fi
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes kernel/main.c -o build/main.o
gcc -Wall -m32 -fno-stack-protector -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/  -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes kernel/init.c -o build/init.o
In file included from kernel/memory.h:4:0,
                 from kernel/init.c:5:
lib/kernel/bitmap.h:12:1: error: unknown type name ‘bool’
 bool bitmap_scan_test(struct bitmap* btmp, uint32_t bit_idx);
 ^
makefile:22: recipe for target 'build/init.o' failed
make: *** [build/init.o] Error 1

Experiência 5

Implemente alocação de memória simples com base no Experimento 4.

Crie os arquivos memory.c e memory.h no diretório do kernel.

root@ubuntu:/home/cooiboi/bochs/kernel# vim memory.c
root@ubuntu:/home/cooiboi/bochs/kernel# vim memory.h

Adicionado um #include "memory.h" e um mem_init(); em /kernel/init.c.

root@ubuntu:/home/cooiboi/bochs/kernel# vim init.c

Adicionado em /lib/kernel/bitmap.htypedef int bool;

Insira a descrição da imagem aqui

Modifique o makefile (nota: você precisa modificá-lo de acordo com seu diretório real)

BUILD_DIR = ./build
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/ 
ASFLAGS = -f elf
CFLAGS = -Wall -m32 -fno-stack-protector $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS =  -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \
      $(BUILD_DIR)/debug.o $(BUILD_DIR)/string.o $(BUILD_DIR)/memory.o \
      $(BUILD_DIR)/bitmap.o
##############     c代码编译     ###############
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h lib/string.h kernel/memory.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h lib/kernel/print.h \
        lib/stdint.h kernel/interrupt.h device/timer.h kernel/memory.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \
        lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/timer.c device/timer.h lib/stdint.h\
        lib/kernel/io.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \
        lib/kernel/print.h lib/stdint.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/string.o: lib/string.c lib/string.h \
	kernel/debug.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/memory.o: kernel/memory.c kernel/memory.h \
	lib/stdint.h lib/kernel/bitmap.h kernel/debug.h lib/string.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/bitmap.o: lib/kernel/bitmap.c lib/kernel/bitmap.h \
	lib/string.h kernel/interrupt.h lib/kernel/print.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@

##############    汇编代码编译    ###############
$(BUILD_DIR)/kernel.o: kernel/kernel.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/print.o: lib/kernel/print.S
	$(AS) $(ASFLAGS) $< -o $@

##############    链接所有目标文件    #############
$(BUILD_DIR)/kernel.bin: $(OBJS)
	$(LD) $(LDFLAGS) $^ -o $@

.PHONY : mk_dir hd clean all

mk_dir:
	if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi

hd:
	dd if=$(BUILD_DIR)/kernel.bin \
           of=/home/cooiboi/bochs/boot/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc

clean:
	cd $(BUILD_DIR) && rm -f  ./*

build: $(BUILD_DIR)/kernel.bin

all: mk_dir build hd

Comece Bochs ~

Insira a descrição da imagem aqui

Use para info tabvisualizar o relacionamento de mapeamento entre endereços virtuais e endereços físicos na tabela de páginas.

O lado esquerdo é o intervalo de endereços virtuais e o lado direito é o endereço físico mapeado.

O intervalo de endereços virtuais é 0x00100000~0x00104fff e o intervalo de endereços físicos mapeados é 0x200000~0x204fff.
Insira a descrição da imagem aqui
Também podemos page 虚拟地址obter o endereço físico usando

Insira a descrição da imagem aqui

Referências

Acho que você gosta

Origin blog.csdn.net/weixin_42888638/article/details/128627195
Recomendado
Clasificación