Lowlevel
Lowlevel => OS-Design => Thema gestartet von: SSJ7Gohan am 20. June 2005, 21:19
-
Hio,
ich habe einen Microkernel, der die Prozessverwaltung und das Memorymanagement übernimmt. Jetzt möchte ich Kernel-Module laden und entladen können die dann in alle Prozesse gemappt werden und vom Kernel über einfache Calls aufgerufen werden sollen. Ich möchte die wichtigsten Treiber nicht als eigene Prozesse laufen lassen, da das die Performance erheblich beeinträchtigen würde.
Mein Problem liegt gedoch darin, wie ich die Kernel-Module laden und ausführen soll:
Normalerweise werden die Programme ja so gelinkt, das sie im Speicher an einer bestimmten Stelle stehen (Text Segment beginnt bei 0x12345 usw. ). Bei den Kernelmodulen weiß ich jedoch erst zur Laufzeit, wohin sie geladen werden. Wie ist es also möglich, sie zu laden? Ich müsste sie ja zur Laufzeit dynamisch linken, weiß jemand, wie das geht? Oder gibt es noch andere Möglichkeiten, die nicht allzu stark die Performance beeinflussen?
mfg,
SSJ7Gohan
-
Dann hast du aber keinen Microkernel sondern einen Modularisierten Monolithischen Kernel! Ansonsten linkst du deine Programme als "relocatable" (z.B. in ELF) und schreibst dann einen Programmteil, der die ELF-Header parst und das Programm an die richtige stelle lädt, wobei alle absoluten Speicherreferenzen umgeschrieben werden.
-
Lade jedes Modul in einen eigenen Virtual Memory Space oder mach Typen (Sound, Grafik, ...), nach denen dann die Adressen fix gemacht werden.
-
Ein eigener Addressraum würde ja eigentlich schon einen eigenen Prozess implizieren, zumindestens 95% des Aufwandes.
-
Ausserdem müsste ich dann bei systemcalls wie z.B. einer read-Operation Daten zwischen Prozessen kopieren, und das ist meiner Meinung nach zu langsam. ^^
An einen festgelegten Ort möchte ich die Module auch nicht laden, da mir das zu unflexibel ist. Ich werde mir dann mal Relocatables im ELF Format ansehen.
-
I am you humble slave and would be honoured if you could tell me how you did that?
-
Here is a piece of c-code, that does elf-relocation, from this thread:
http://lowlevel.brainsware.org/forum/viewtopic.php?t=907
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef long s32;
typedef short s16;
#define ELF386_SEC_SYMTABLE 2
#define ELF386_R_32 1
#define ELF386_R_PC32 2
#define ELF386_R_SYMBOL(z) ( (z) >> 8 )
#define ELF386_R_TYPE(z) ( (unsigned char)(z) )
#define ELF386_ST_BINDING(z) ( (z) >> 4 )
#define ELF386_ST_TYPE(z) ( (z) & 0xF )
#define ELF386_MAGINDEX_0 0
#define ELF386_MAGINDEX_1 1
#define ELF386_MAGINDEX_2 2
#define ELF386_MAGINDEX_3 3
#define ELF386_MAG_0 0x7F
#define ELF386_MAG_1 'E'
#define ELF386_MAG_2 'L'
#define ELF386_MAG_3 'F'
typedef struct {
u8 elfMagic[16];
u16 elfType;
u16 elfMachine;
u32 elfVersion;
u32 elfEntry;
u32 elfProgramOffset;
u32 elfSectionOffset;
u32 elfFlags;
u16 elfHeaderSize;
u16 elfProgramSize;
u16 elfProgramCount;
u16 elfSectionSize;
u16 elfSectionCount;
u16 elfStringSection;
} __attribute__ ((packed)) elf386Header;
typedef struct {
u32 sectionName;
u32 sectionType;
u32 sectionFlags;
u32 sectionAddress;
u32 sectionOffset;
u32 sectionSize;
u32 sectionLink;
u32 sectionInfo;
u32 sectionAlign;
u32 sectionEntrySize;
} __attribute__ ((packed)) elf386Section;
typedef struct {
u32 symbolName;
u32 symbolValue;
u32 symbolSize;
u8 symbolInfo;
u8 symbolOther;
u16 symbolSection;
} __attribute__ ((packed)) elf386Symbol;
typedef struct {
u32 relocOffset;
u32 relocInfo;
s32 relocAdded;
} __attribute__ ((packed)) elf386Relocation;
typedef struct {
u32 programType;
u32 programOffset;
u32 programVirtualAddress;
u32 programPhysicalAddress;
u32 programFileSize;
u32 programSize;
u32 programFlags;
u32 programAlign;
} __attribute__ ((packed)) elf386ProgramHeader;
void *elf386LoadModule( char *image, unsigned long size );
int elf386Relocate( char *image );
int elf386DoRelocation( char *image, elf386Section *section, elf386Relocation *relocation );
unsigned long elf386GetSymbol( char *image, unsigned long symbolTable, unsigned long symbolID );
void *elf386GetSymbolOffset( char *image, char *name );
// in memory.h steht die Funktion allocateSystemMemory(), die benutzt wird um die Module zu laden.
#include "../memory.h"
#include "string.h"
void *elf386LoadModule( char* image, unsigned long size ) {
elf386Header *header = (elf386Header *)image;
elf386Section *section;
if ((header->elfMagic[ELF386_MAGINDEX_0] != ELF386_MAG_0) ||
(header->elfMagic[ELF386_MAGINDEX_1] != ELF386_MAG_1) ||
(header->elfMagic[ELF386_MAGINDEX_2] != ELF386_MAG_2) ||
(header->elfMagic[ELF386_MAGINDEX_3] != ELF386_MAG_3)) {
return -1;
}
unsigned long bssSize;
// loop trough the sections and look for the bss section
unsigned long i;
for( i = 0; i < header->elfSectionCount; i++ ) {
section = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * i );
if( section->sectionType != 8 )
continue;
bssSize = section->sectionSize;
break;
}
// allocate memory for the module
void *module = (void *)allocateSystemMemory( size + bssSize );
// copy the image into memory
memcpy( module, image, size );
// zero the bss section
memset( module + size, 0, bssSize );
// setup the bss section
section->sectionOffset = (u32)module + size;
return module;
}
int elf386Relocate( char *image ) {
unsigned long i;
unsigned long j;
elf386Section *section;
elf386Header *header = (elf386Header *)image;
elf386Relocation *relocation;
if ((header->elfMagic[ELF386_MAGINDEX_0] != ELF386_MAG_0) ||
(header->elfMagic[ELF386_MAGINDEX_1] != ELF386_MAG_1) ||
(header->elfMagic[ELF386_MAGINDEX_2] != ELF386_MAG_2) ||
(header->elfMagic[ELF386_MAGINDEX_3] != ELF386_MAG_3)) {
return -1;
}
unsigned long relocSize;
// now we loop trough the sections and look for relocation infos
for( i = 0; i < header->elfSectionCount; i++ ) {
section = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * i );
if( section->sectionType == 4 ) {
relocSize = 12;
}else if( section->sectionType == 9 ) {
relocSize = 8;
}else{
continue;
}
// the section contains relocation infos
for( j = 0; j < section->sectionSize / relocSize; j++ ) {
relocation = (elf386Relocation *)( image + section->sectionOffset + relocSize * j );
// do the relocation
elf386DoRelocation( image, section, relocation );
}
}
}
int elf386DoRelocation( char *image, elf386Section *section, elf386Relocation *relocation ) {
elf386Header *header = (elf386Header *)image;
elf386Section *targetSection = (elf386Section *)(image + header->elfSectionOffset + header->elfSectionSize * section->sectionInfo);
unsigned long *relocationOffset = (unsigned long *)( image + targetSection->sectionOffset + relocation->relocOffset );
unsigned long symbol = elf386GetSymbol( image, section->sectionLink, ELF386_R_SYMBOL( relocation->relocInfo ) );
switch( ELF386_R_TYPE( relocation->relocInfo ) ) {
case ELF386_R_32 :
*relocationOffset = *relocationOffset + symbol;
break;
case ELF386_R_PC32 :
*relocationOffset = *relocationOffset + symbol - (unsigned long)relocationOffset;
break;
}
}
unsigned long elf386GetSymbol( char *image, unsigned long symbolTable, unsigned long symbolID ) {
elf386Header *header = (elf386Header *)image;
elf386Section *table = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * symbolTable );
elf386Symbol *symbol = (elf386Symbol *)( image + table->sectionOffset ) + symbolID;
elf386Section *section;
if( symbol->symbolSection == 0 ) {
// external symbol
section = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * table->sectionLink );
return lookupExternalSymbols( (char *)( image + section->sectionOffset + symbol->symbolName ) );
}else{
// internal symbol
section = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * symbol->symbolSection );
return (unsigned long)( image + section->sectionOffset + symbol->symbolValue );
}
}
void *elf386GetSymbolOffset( char *image, char *name ) {
elf386Header *header = (elf386Header *)image;
elf386Section *section;
elf386Section *strings;
elf386Symbol *symbol;
elf386Section *symbolSection;
if ((header->elfMagic[ELF386_MAGINDEX_0] != ELF386_MAG_0) ||
(header->elfMagic[ELF386_MAGINDEX_1] != ELF386_MAG_1) ||
(header->elfMagic[ELF386_MAGINDEX_2] != ELF386_MAG_2) ||
(header->elfMagic[ELF386_MAGINDEX_3] != ELF386_MAG_3)) {
return 0;
}
// loop trough the sections and look for the text section
unsigned long i;
unsigned long j;
for( i = 0; i < header->elfSectionCount; i++ ) {
section = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * i );
if( section->sectionType == ELF386_SEC_SYMTABLE ) {
strings = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * section->sectionLink );
for( j = 0; j < section->sectionSize / sizeof( elf386Symbol ); j++ ) {
symbol = (elf386Symbol *)( image + section->sectionOffset ) + j;
if( strcmp( image + strings->sectionOffset + symbol->symbolName, name ) == 0 ) {
symbolSection = (elf386Section *)( image + header->elfSectionOffset + header->elfSectionSize * symbol->symbolSection );
return image + symbolSection->sectionOffset + symbol->symbolValue;
}
}
}
}
return 0;
}
-
Ich glaub, du hast nem Bot eine Frage beantwortet :lol: !
-
Könnte sein^^
-
Na, da hat der Bot aber eine sehr passende Frage gestellt.
-
Findest du ? Warum dann auf Englisch, wenn der ganze Theard auf Deutsch ist ???? Man könnte ihn ja mal testen. Weiss nicht ??
Diese Frage könnte man unter praktisch jedes Thema setzen, oder der im Lyrik-Eck, welcher Idiot sagt denn sowas: Der Bot hat nur den ersten Satz genommen und was dazugeschrieben, was auch für sehr viele Therds geht.