Lowlevel

Lowlevel => Softwareentwicklung => Thema gestartet von: Martin Erhardt am 23. December 2012, 22:59

Titel: gcc spinnt(Linkerfehler)[Solved]
Beitrag von: Martin Erhardt 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
Titel: Re: gcc spinnt(Linkerfehler)[Solved]
Beitrag von: kevin 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.
Titel: Re: gcc spinnt(Linkerfehler)[Solved]
Beitrag von: Martin Erhardt 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