Como desenvolver um módulo executável

Este documento apresenta como é o processo de desenvolvimento de um módulo executável (um programa).

Um módulo executável não implementa nenhuma interface e também não fornece funções para outros módulos. Na verdade, é ele que deve usar os módulos biblioteca e os módulos do sistema para fazer algo de útil.

O desenvolvimento de um módulo executável é como o desenvolvimento de um programa em C nos outros sistemas operacionais, com duas particularidades.

A primeira está relacionada com o utilitário que converte os arquivos .o (ELF), gerados pelo compilador GCC, para arquivo de módulo executável. A função que inicia o programa (função main nos programas em C) deve ter um atributo especial. Por exemplo:

void main(int argc, char *argv[], char *envp[]) __attribute__ ((section (".init")));

void main(int argc, char *argv[], char *envp[]) {
...
meu código
...
}

Esse atributo diz para colocar a função main do exemplo na seção .init do arquivo ELF.

A segunda peculiaridade está relacionada com o uso de módulos biblioteca. Todos os módulos biblioteca usados pelo módulo executável devem ser iniciados antes de serem utilizados e terminados antes do módulo executável terminar.

Um exemplo de módulo executável que usa duas interfaces do usuário:

#include "intermanager.h"
#include "usermodmanager.h"
#include "textvideo.h"
#include "lib/memmanager.h"
#include "lib/stringman.h"

int (*TV_Write)(const char*);

void main(void) __attribute__ ((section (".init")));

void StartLibs(void) {
    unsigned int i;
    int (*start)(void);

    i = 0;
    while ((start = UserModManager_UGetStartFunctionI(i++))) {
        if ((unsigned int)start != 0xffffffff && start()) {
            TV_Write("Error starting lib.\n");
            UserModManager_UExit(2);
        }
    }
}

void ShutdownLibs(void) {
    unsigned int i;
    int (*shutdown)(void);

    i = 0;
    while ((shutdown = UserModManager_UGetShutdownFunctionI(i++))) {
        if ((unsigned int)shutdown != 0xffffffff && shutdown()) {
            TV_Write("Error stoping lib.\n");
        }
    }
}

int GetTVFunction(void) {
    int ret;
    char outBuf[256];
    InterManager_OutputInfo *outInfo;

    /* get TextVideo functions */
    outInfo = (InterManager_OutputInfo*)outBuf;
    ret = InterManager_UGetOutputInfo(outInfo, sizeof(outBuf));
    if (ret) {
        return ret;
    }
    return UserModManager_UGetFunction(outInfo->names, outInfo->names+outInfo->interSize, TextVideo__UWRITE, UserModManager_SYS_FUNCTION, (void**)&TV_Write);
}

void main(void) {
    if (GetTVFunction()) {
        UserModManager_UExit(1);
    }
    StartLibs();
...
meu código
...
    ShutdownLibs();
    UserModManager_UExit(0);
}

Como se nota as bibliotecas são iniciadas e no final são terminadas.