Autor Thema: Implementation von Kernelmodulen  (Gelesen 11873 mal)

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« 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

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 21. June 2005, 00:05 »
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.
Agieren statt Konsumieren!

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #2 am: 21. June 2005, 13:21 »
Lade jedes Modul in einen eigenen Virtual Memory Space oder mach Typen (Sound, Grafik, ...), nach denen dann die Adressen fix gemacht werden.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #3 am: 21. June 2005, 13:50 »
Ein eigener Addressraum würde ja eigentlich schon einen eigenen Prozess implizieren, zumindestens 95% des Aufwandes.
*post*

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 21. June 2005, 16:10 »
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.

Anonymous

  • Gast
Gespeichert
« Antwort #5 am: 02. December 2005, 08:00 »
I am you humble slave and would be honoured if you could tell me how you did that?

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 02. December 2005, 14:43 »
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;
}

Azi

  • Beiträge: 47
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 02. December 2005, 16:04 »
Ich glaub, du hast nem Bot eine Frage beantwortet :lol: !

Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen nicht.

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann. Das Gegenteil ist schon schwieriger.

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 02. December 2005, 16:21 »
Könnte sein^^

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #9 am: 02. December 2005, 19:03 »
Na, da hat der Bot aber eine sehr passende Frage gestellt.
*post*

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 02. December 2005, 19:21 »
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.

 

Einloggen