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!
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 ):
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.
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!
¿Has indicado el directorio
¿Has indicado el directorio de páginas al CPU? En principio no veo ningun error en el código...
Si quieres te paso el code
Si quieres te paso el code para que veas el "SO", pero te lo envio por MP.
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:
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:
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!
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:
Está tomado del tutorial de Bran, así que debería de estara perfectamente escrito.
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.
Pues no se, prueba a ver si
Pues no se, prueba a ver si mapeando menos memoria( 1 MB o así ) funciona.