Autor Thema: gcc spinnt(Linkerfehler)[Solved]  (Gelesen 7038 mal)

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« am: 23. December 2012, 22:59 »
Ich kriege folgende LinkerFehler:
Das macht keinen Sinn mtenabled ist vorschriftsmäßig als extern markiert und time kommt in irq.c nichtmal vor.
mt/ts.o: In function `init_task':
/home/martin/git/el_toro_repo/src/mt/ts.c:16: multiple definition of `mtenabled'
driver/timer/timer.o:/home/martin/git/el_toro_repo/src/driver/timer/timer.c:9: first defined here
intr/irq.o: In function `handle_irq':
/home/martin/git/el_toro_repo/src/intr/irq.c:8: multiple definition of `time'
driver/timer/timer.o:/home/martin/git/el_toro_repo/src/driver/timer/timer.c:9: first defined here
Selbst wenn ich timer.c und .h  komplett wegkommentiere kommt immernoch:
mt/ts.o: In function `init_task':
/home/martin/git/el_toro_repo/src/mt/ts.c:16: multiple definition of `mtenabled'
driver/timer/timer.o:(.bss+0x0): first defined here
irq.c
#include <console.h>
#include <irq.h>
#include <cpustate.h>
#include "../driver/keyboard/keyboard.h"
#include "../driver/timer/timer.h"
#include<ioport.h>
cpu_state* handle_irq(cpu_state* cpu)

cpu_state* new_cpu = cpu;

if (cpu->intr >= 0x28) {
            // EOI an Slave-PIC
            outb(0xa0, 0x20);
}else if(cpu->intr==0x21){kbc_handler(0x21);}
else if(cpu->intr==0x20){timer_handler(&new_cpu);}
// EOI an Master-PIC
outb(0x20, 0x20);
return new_cpu;
}
timer.c
#include<stdint.h>
#include<cpustate.h>
#include<ts.h>
#include<stdbool.h>
#include"timer.h"

//extern bool mtenabled;

void timer_handler(cpu_state* new_cpu){
    time++;
    if(mtenabled){
new_cpu=schedule(new_cpu);
    }
}
timer.h:
#ifndef TIMER_H
#define TIMER_H

#include<stdint.h>
#include<cpustate.h>

extern bool mtenabled;
uint32_t time=0;
void timer_handler(cpu_state* new_cpu);

#endif
ts.c:
#include <cpustate.h>
#include <stdint.h>
#include <stdbool.h>
#include "ts.h"

static int current_task = -1;
static int num_tasks=0;
static task tasks[MAX_CPUSTATE];

/*
 * Jeder Task braucht seinen eigenen Stack, auf dem er beliebig arbeiten kann,
 * ohne dass ihm andere Tasks Dinge ueberschreiben. Ausserdem braucht ein Task
 * einen Einsprungspunkt.
 */
task* init_task(void* entry)
{
    if(!mtenabled){
mtenabled=TRUE;
    }
    /*
     * CPU-Zustand fuer den neuen Task festlegen
     */
    cpu_state new_state = {
        .eax = 0,
        .ebx = 0,
        .ecx = 0,
        .edx = 0,
        .esi = 0,
        .edi = 0,
        .ebp = 0,
        //.esp = unbenutzt (kein Ring-Wechsel)
        .eip = (uint32_t) entry,
 
        /* Ring-0-Segmentregister */
        .cs  = 0x08,
        //.ss  = unbenutzt (kein Ring-Wechsel)
 
        /* IRQs einschalten (IF = 1) */
        .eflags = 0x202,
    };
    /*
     * Stack erstellen
     */
    uint8_t new_stack[STDRD_STACKSIZE];
    /*
     * Den angelegten CPU-Zustand auf den Stack des Tasks kopieren, damit es am
     * Ende so aussieht als waere der Task durch einen Interrupt unterbrochen
     * worden. So kann man dem Interrupthandler den neuen Task unterschieben
     * und er stellt einfach den neuen Prozessorzustand "wieder her".
     */
    cpu_state* state = (void*) (&new_stack + STDRD_STACKSIZE - sizeof(new_state));
    *state = new_state;
   
    num_tasks++;
    /*
     * neuen Task struct erstellen, in die Liste eintragen und zurückgeben
     */
    task new_task ={state,new_stack,num_tasks};
    tasks[num_tasks]=new_task;
 
    return &new_task;
}
/*
 * Gibt den Prozessorzustand des naechsten Tasks zurueck. Der aktuelle
 * Prozessorzustand wird als Parameter uebergeben und gespeichert, damit er
 * beim naechsten Aufruf des Tasks wiederhergestellt werden kann
 */
cpu_state* schedule(cpu_state* cpu)
{
    /*
     * Wenn schon ein Task laeuft, Zustand sichern. Wenn nicht, springen wir
     * gerade zum ersten Mal in einen Task. Diesen Prozessorzustand brauchen
     * wir spaeter nicht wieder.
     */
    if (current_task >= 0) {
        tasks[current_task].state = cpu;
    }
    /*
    * Naechsten Task auswaehlen. Wenn alle durch sind, geht es von vorne los
    */
    current_task++;
    current_task %= num_tasks;

    /* Prozessorzustand des neuen Tasks aktivieren */
    cpu = tasks[current_task].state;

    return cpu;
}
ts.h
#ifndef TS_H
#define TS_H

#include<stdint.h>
#include<cpustate.h>
#include <stdbool.h>

#define STDRD_STACKSIZE 4096 //Stack größe bei der Initialisierung
#define MAX_CPUSTATE 32 // Maximal zahl an Tasks noch keine malloc() funktion implementiert

bool mtenabled=FALSE;

typedef struct {
    cpu_state *state;
    uint8_t stack_a[STDRD_STACKSIZE];
    uint32_t pid;
} task;
task* init_task(void* entry);
cpu_state* schedule(cpu_state* cpu);
#endif
Vielen Dank für die Hilfe
« Letzte Änderung: 24. December 2012, 00:24 von Martin Erhardt »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 24. December 2012, 00:50 »
Kurze Antwort: Lern C.

Lange Antwort: Variablen gehören nicht in Headerfiles definiert. Die Definition gehört in eine .c-Datei und in den Header kommt nur eine extern-Deklaration. Sonst definiert jede Datei, die den Header einbindet, eine eigene Variable mit diesem Namen und das geht nicht gut.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 24. December 2012, 01:02 »
Achso,
Kleine Wissenslücke. Ich verwende normalerweise auch kaum globale Variablen soll man ja nicht (http://ubuntuforums.org/showthread.php?t=658778) :-D
« Letzte Änderung: 24. December 2012, 01:05 von Martin Erhardt »

 

Einloggen