Anuncios Google

Problemas con el gestor de memoria [SOLUCIONADO]

 

Estoy diseñando un SO por mi cuenta, y actualmente diseño la parte que corresponde a la gestion de la memoria RAM.

Uso paginacion, pero las direcciones virtuales son exatamente iguales que las fisicas.

La memoria RAM la divido en fragmentos dinamicos,que se relacionan con la cabecera MIIOS_Alloc_Node, que actua como una lista enlazada.

Emulo el "SO" con VirtualBox con una memoria RAM de 32MB, de la cual reservo los 8 primeros MegaBytes para el Sistema y el resto lo uso para peticiones de memoria.

Como vereis solo hay 3 funciones muy simples, en el codigo que hay abajo, y las otras funciones que aparecen son muy sencillas, por lo que si alguien responde, deduzco que no necesitan explicacion alguna.

Se que para algunos este codigo es muy simple, muy poco eficiente y muy poco seguro, pero... soy principiante.

 

 

CODIGO DE LA CABECERA:

#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H
	#include <types.h>
 
	#define ALLOC_NODE_USED 1
	#define ALLOC_NODE_END  (1<<7)
 
	struct __attribute__((__packed__)) __alloc_node{
		struct __alloc_node* last;
		struct __alloc_node* next;
		u8 flags; // El primer bit indica si se usa.
				  // El ultimo bit indica si es la ultima pagina
	};
 
 
	typedef struct __alloc_node MIIOS_Alloc_Node;
 
	static MIIOS_Alloc_Node* MMfirst;
 
	void InitMMU();
 
	// Peticion de memoria
	void* kmalloc(u32 bytes);
 
	// Liberar memoria
	void kfree(void* ptr);
 
#endif

 

CODIGO DEL CUERPO:

#include <mmu.h>
#include <types.h>
#include <paging.h>
 
	void InitMMU(){
		// Este el ultimo nodo , esta en el MB 32 - 15 bytes
		MIIOS_Alloc_Node* end=(MIIOS_Alloc_Node*)0x1FFFFF0;
 
		// Este es el primer nodo, esta en el MB 8
		MMfirst=(MIIOS_Alloc_Node*)0x800000;
 
		// Enlazamos los nodos
		MMfirst->last=NULL;	// No hay un nodo anterior al primero (obvio)
		MMfirst->next=end;	// El siguiente nodo, es el ultimo
		MMfirst->flags=0;	// Esta libre
 
		end->last=MMfirst;	// El anterior nodo, es el primero
		end->next=NULL;		// No hay un nodo siguiente al ultimo (obvio)
		end->flags=(1<<7)|1;// Esta usado y ademas es el ultimo nodo
 
 
	}
 
	void* kmalloc(u32 bytes){
 
		MIIOS_Alloc_Node* tmp;
		MIIOS_Alloc_Node* tmp2;
 
		for(tmp=MMfirst; tmp->next!=NULL, tmp!=NULL, (tmp->flags&(1<<7))!=(1<<7); tmp=tmp->next){
			if((tmp->flags&(1<<7))==(1<<7)) break;
			if(tmp==NULL) break;
 
			if(tmp->flags&0x01==0){	// Hay un nodo libre
				if((u32)(tmp->next-tmp)==bytes+10){	// El nodo tiene el mismo 
													//tamaño que lo que se necesita
					tmp->flags|=1;	// Ponemos el bit 0 en usado
					return (void*)(tmp+sizeof(MIIOS_Alloc_Node));
				}
 
				if((u32)(tmp->next-tmp)>bytes+10){	// El tamaño del nodo es mayor
					// Si es menos de 18 mayor que el espacio requerido
					if(((u32)(tmp->next-tmp))-(bytes+10)<18){
						tmp->flags|=1;
						return (void*)(tmp+sizeof(MIIOS_Alloc_Node));
					}
					// Sino...
					tmp2=(MIIOS_Alloc_Node*)tmp+bytes+10;
 
					// Creamos otro nodo que vaya donde termine el que
					// vamos a usar y lo enlazamos con los demas
					tmp2->next=tmp->next;
					tmp2->last=tmp;
					tmp2->flags=0;
 
					tmp->next->last=tmp2;
 
					tmp->next=tmp2;
					tmp->flags=1;
					return (void*)(tmp+sizeof(MIIOS_Alloc_Node));
				}
			}
		}
		return NULL;
	}
 
	void kfree(void* ptr){
		// Obtenemos el nodo al que corresponde la direccion
		MIIOS_Alloc_Node* node=ptr-sizeof(MIIOS_Alloc_Node);
		if(node->flags==0) return;	// El nodo no esta usado
		if((node->flags&(1<<7))==(1<<7)) return;	// El ultimo nodo
 
		node->flags=0;	// Ponemos el bit 0 en libre
		// Vamos a comprobar si hay nodo libres delante...
		MIIOS_Alloc_Node* tmp;
		for(tmp=node->next; tmp!=NULL, tmp->flags&1!=1, (tmp->flags&(1<<7))!=(1<<7); tmp=tmp->next){
			if(node->flags&1==1) break;
			if((node->flags&(1<<7))==(1<<7)) break;
			if(tmp==NULL) break;
		}
		// si los hay los unimos todos en uno solo
		node->next=tmp;
		tmp->last=node;
 
		// Vamos a ver si hay nodos libres detras...
		for(tmp=node->last; tmp!=NULL, tmp->flags&1!=1, (tmp->flags&(1<<7))!=(1<<7); tmp=tmp->last){
			if(node->flags&1==1) break;
			if((node->flags&(1<<7))==(1<<7)) break;
			if(tmp==NULL) break;
		}
		// si los hay los unimos todos
		tmp=tmp->next;
 
		tmp->next=node->next;
		node->next->last=tmp;
 
		return;
	}
 
 

 

- Bueno tras esto le planteo mi problema:

Tras iniciar el gestor intento hacer una peticion de memoria, pero siempre me devuelve NULL.

 

CODIGO

extern void __enable_a20();
 
	void _init(){
		ScreenClear();
		LoadDefaultGDT();
		RunProtectedMode();
		PIC_ReMap(0x20,0x28);
		__enable_a20();
		LoadDefaultIDT();
		InstallExceptionINT();
	        printf("Iniciando paginacion....\n");
		Identy_PagingInit();
		printf("[OK]\nIniciando Gestor de Memoria...\n");
		InitMMU();
		printf("[OK]\n");
		printf("Realizando Test de alojacion con kmalloc\n");
		s8* test=(s8*) kmalloc (40);
		memset(test, 0, 40);
		strcpy(test, "Prueba de malloc\n");
		printf("%x\n", (u32)test);
		printf("%s\n", test);
		printf("Liberando memoria...\n");
		kfree(test);
		while(1) hlt();
	}

¿Alguien puede ayudarme? 

 

Estoy desesperado, harto de intentarlo, siempre devuelve NULL.

 

 


Programo en C, C++, C# y ASM ( Sintaxis INTEL y AT&T )

Proyectos:

- UnlockMii 5.0 ----> UnlockMii 5.1: ( EN CONSTRUCCION -> 2% )

- MiiOS ( EN CONSTRUCCION -> 0,01% )

El mejor antivirus ==> Avast!


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de Almamu

Grave error el que tienes. Si

Grave error el que tienes. Si lo que creo es verdad, tu sistema operativo está funcionando en modo Real( http://wiki.osdev.org/Real_Mode ), es decir, que no puede pasar del 1MB de RAM para tu uso. Según veo estás tratando de acceder a memoria por encima de 1 MB, además no tienes activada la gate a20, por lo que todo son limitaciones. Para poder activar el modo protegido( y tener acceso a más de 1 MB de RAM ) tienes que tener también las tablas GDT/IDT.

Para activar el modo protegido tienes que crear primero las tablas para el GDT y el IDT, indicarselas al procesador y luego poner el bit 1 del registro cr0 a 1. En principio, con esto puedes activar el modo protegido( tambien, como opcional, activar la puerta a20, es muy sencillo, se usa el I/O del teclado para mandar el comando de activacion del a20, mas info http://wiki.osdev.org/A20 ):

; El punto de entrada del kernel
start:
        cli                 ; Desactivamos interrupciones
        lgdt [gdtr]      ; Indicamos al CPU la tabla GDT
 
        ; Activamos modo protegido
        mov eax, cr0
        or al, 1
        mov cr0, eax
 
        ; Después saltas(salto lejano o far jump) al segmento de codigo en el GDT
        jmp 08h:pmode
 
pmode:
        call main ; Nuestra funcion en C

Luego puedes activar la paginación de memoria. De todas formas, si te quieres evitar todo esto de momento, simplemente configuralo para que no pase del megabyte de memoria, el modo protegido es algo para más adelante.

Te recomiendo esta wiki http://wiki.osdev.org/ tiene mucha información sobre la programación de un sistema operativo, además de tener un foro donde puedes resolver tus dudas. Además, si necesitas alguna guía puedes mirar este tutorial: http://www.jamesmolloy.co.uk/tutorial_html/ está bastante bien, y aunque el código es bastante antiguo( está basado en el tutorial de Bran's, que es aun mas viejo )funciona todo a la perfección.


Imagen de ateno_3

En realidad si que esta en

En realidad si que esta en modo protegido, lo que ocurre es que no lo he puesto en el trozo de codigo que aparece.

Ademas también tengo cargadas la GDT e IDT.

Gracias por comentarme lo del gate A20, intentare activarlo y ya te comentare.

La pagina que me dices ya la conozco (wiki.osdev), ademas es el lugar de donde yo extraigo la informacion.

 

EDITO: Ya he probado habilitando el gate A20, pero aun asi, sigue sin funcionar, devuelve NULL.


Programo en C, C++, C# y ASM ( Sintaxis INTEL y AT&T )

Proyectos:

- UnlockMii 5.0 ----> UnlockMii 5.1: ( EN CONSTRUCCION -> 2% )

- MiiOS ( EN CONSTRUCCION -> 0,01% )

El mejor antivirus ==> Avast!

Imagen de Almamu

¿Has indicado el directorio

¿Has indicado el directorio de páginas al CPU? En principio no veo ningun error en el código...

Imagen de ateno_3

Si quieres te paso el code

Si quieres te paso el code para que veas el "SO", pero te lo envio por MP.

Imagen de Almamu

Para empezar, según veo en tu

Para empezar, según veo en tu código lanzas el modo protegido pero no haces un farjump al codigo, por lo que realmente no estás en el modo protegido. Además, el a20m el gdt y el idt se hacen antes de saltar a modo protegido:

global _loader
global eokl
global pmode
 
extern _init
extern RunProtectedMode
extern LoadDefaultGDT
extern LoadDefaultIDT
extern __enable_a20
 
; ESTRUCTURA DE GRUB
MODULEALIGN equ  1<<0
MEMINFO     equ  1<<1
FLAGS       equ  MODULEALIGN | MEMINFO
MAGIC       equ    0x1BADB002
CHECKSUM    equ -(MAGIC + FLAGS) 
 
STACKSIZE equ 0x4000 ; 16kb ( 4 paginas )
 
section .text
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
eokl dd stack+STACKSIZE
 
_loader:
	mov esp, stack+STACKSIZE
 
	; Cargamos a gate a20
	call __enable_a20
 
	; Cargamos el IDT y el GDT
	call LoadDefaultGDT
	call LoadDefaultIDT
 
	; Activamos el modo protegido
	mov eax, cr0
	or al, 1
	mov cr0, eax
 
	; Farjump a pmode
	jmp 08h:pmode
 
pmode:
	push eax
	push ebx
	call _init
	again:
		hlt
	jmp again
 
section .bss
	align 4
stack: 
		resb STACKSIZE
 

Con esto debería de funcionar. No lo puedo probar porque no estoy en mi PC, De todas formas luego lo probaré a ver.

Además, no necesitas desactivar la paginacion de memoria, simplemente la debes activar después de indicarle el directorio de paginas por cr3:

    asm volatile("mov %0, %%cr3":: "r"(dir->physicalAddr)); // Indicamos el directrio al procesador
    u32int cr0;
    asm volatile("mov %%cr0, %0": "=r"(cr0));
    cr0 |= 0x80000000; // Activamos la paginacion
    asm volatile("mov %0, %%cr0":: "r"(cr0));

 


Imagen de ateno_3

Gracias por contestar, pero

Gracias por contestar, pero cuando intento hacer un far jump al codigo, la maquina virtual se bloque y no continua.

La maquina virtual es VirtualBox 4.1.8


Programo en C, C++, C# y ASM ( Sintaxis INTEL y AT&T )

Proyectos:

- UnlockMii 5.0 ----> UnlockMii 5.1: ( EN CONSTRUCCION -> 2% )

- MiiOS ( EN CONSTRUCCION -> 0,01% )

El mejor antivirus ==> Avast!

Imagen de Almamu

Según veo no indicas los bits

Según veo no indicas los bits al compilador ASM en el bootloader:

bits 32

Pon eso al principio del archivo y vuelve a probar.

Además, no tengo ni idea de si el script del linker está bien escrito, no se me da muy bien, por si acaso, puedes probar este:

ENTRY(start)
SECTIONS
{
 
    .text 0x100000 :
    {
        code = .; _code = .; __code = .;
        *(.text)
        . = ALIGN(4096);
    }
 
    .data :
    {
        data = .; _data = .; __data = .;
        *(.data)
        *(.rodata)
        . = ALIGN(4096);
    }
 
    .bss :
    {
        bss = .; _bss = .; __bss = .;
        *(.bss)
        . = ALIGN(4096);
    }
 
    end = .; _end = .; __end = .;
}

Está tomado del tutorial de Bran, así que debería de estara perfectamente escrito.


Imagen de ateno_3

Ya he puesto de lo bits 32, y

Ya he puesto de lo bits 32, y he probado el script, pero sigue sin funcionar.

Gracias de todas formas.

Imagen de Almamu

Pues no se, prueba a ver si

Pues no se, prueba a ver si mapeando menos memoria( 1 MB o así ) funciona.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.