Deine Programme können entweder über Callgates oder über Interrupts/Traps mit dem Kernel kommunizieren.
In einem Microkernel sind die Treiber Prozesse, und sie werden über IPC wie z.b. Sockets oder FIFOs angesprochen.
Cygwin stellt Posixfunktionen unter Windows bereit, so kann man z.B. den gcc von Cygwin benutzen um ein OS zu kompilen, DJGPP ist aber auch nicht schlechter.
ELF Files sind eigentlich ganz leicht zu lesen, dazu gibt es z.B. bei OSDR ein Dokument.
Hier sind einige Codeschnippsel. Der Code stammt eigentlich aus LegendOS, ich habe ihn nur geringfügig geändert
Header:
/* LegendOS - Operating System
* Copyright (C) 2003 Joachim Nock
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ELF_H__
#define __ELF_H__
/* *** ELF Header *** */
#define EI_NIDENT 16
/* Elf32_Ehdr->e_ident */
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define ELFMAG0 0x7F
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFCLASS32 1
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
/* Elf32_Ehdr->e_type */
#define ET_EXEC 2
#define ET_DYN 3
/* Rest seems unintersting for a kernel */
/* Elf32_Ehdr->e_version */
#define EV_CURRENT 1
/* Elf3_Ehdr->e_machine */
#define EM_386 3
/* Only platform that I'm developing for at this moment */
struct Elf32_Ehdr {
unsigned char e_ident[EI_NIDENT];
unsigned short e_type;
unsigned short e_machine;
unsigned long e_version;
unsigned long e_entry;
unsigned long e_phoff;
unsigned long e_shoff;
unsigned long e_flags;
unsigned short e_ehsize;
unsigned short e_phentsize;
unsigned short e_phnum;
unsigned short e_shentsize;
unsigned short e_shnum;
unsigned short e_shstrndx;
} __attribute__ ((packed));
typedef struct Elf32_Ehdr Elf32_Ehdr;
/* *** Program header *** */
/* Elf32_Phdr->p_type */
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define LT_HIPROC 0x7FFFFFFF
struct Elf32_Phdr {
unsigned long p_type;
unsigned long p_offset;
unsigned long p_vaddr;
unsigned long p_paddr;
unsigned long p_filesz;
unsigned long p_memsz;
unsigned long p_flags;
unsigned long p_align;
} __attribute__ ((packed));
typedef struct Elf32_Phdr Elf32_Phdr;
#endif /* __ELF_H__ */
Diese Funktion erzeugt ein Prozess aus einer in den Speicher geladenen ELF File: void createProcessFromElf( char *id, char *buffer ) {
tProcess *newProcess;
unsigned long i;
Elf32_Ehdr* header = (Elf32_Ehdr*)buffer;
if ((header->e_ident[EI_MAG0] != ELFMAG0) ||
(header->e_ident[EI_MAG1] != ELFMAG1) ||
(header->e_ident[EI_MAG2] != ELFMAG2) ||
(header->e_ident[EI_MAG3] != ELFMAG3)) {
printf("Unsupported file format\n");
return;
}
newProcess = createProcess( id, (void *)header->e_entry, 0, 0 );
setPageDirectory( resolveAddress( g_memorySystemDirectory, (unsigned long)newProcess->processPages) );
Elf32_Phdr *pheader = (Elf32_Phdr*)&buffer[header->e_phoff];
for( i = 0; i < header->e_phnum; i++, pheader++) {
// allocate memory for the section
if( pheader->p_memsz > 0 ) {
unsigned long padding = pheader->p_vaddr % 4096;
directoryAllocateBetween( newProcess->processPages, pheader->p_vaddr - padding, pheader->p_vaddr + pheader->p_memsz + padding );
memset( (void *)(pheader->p_vaddr - padding), 0, pheader->p_memsz + padding );
memcpy( (void *)(pheader->p_vaddr - padding), &buffer[pheader->p_offset - padding], pheader->p_filesz + padding );
}
}
setPageDirectory( resolveAddress( g_memorySystemDirectory, (unsigned long)g_memorySystemDirectory ) );
printf( "ELF File Entry %X\n", header->e_entry );
newProcess->next = parentProcess->next;
parentProcess->next = newProcess;
}
Die obrige Funktion erwartet einen String, der jedoch nur der Identifikation des Prozesses in meinem OS dient und den Pointer auf eine ELF File und erzeugt einen Prozess aus der ELF File, indem sie ein Pagedirectory für den Prozess erstellt, die Segmente der ELF File dort reinkopiert und den Prozess in eine linked list für den Scheduler schreibt.
Die Funktion directoryAllocateBetween( unsigned long *directory, unsigned long start, unsigned long end ) allocated alle pages zwischen den Addressen start und end im directory directory.
Du wirst warscheinlich die memory und prozesse nicht so wie ich implementieren, aber so gewinnst du schonmal einen Eindruck, wie man die Files läd. Bei shared libs wird das ganze noch komplizierter, da man dann die Relocate und Symboltables usw. lesen muss.