Specifikation Abstrakt, objektorienteret operativsystem-api
Indhold 1 Indledning... 3 1.1 Introduktion... 3 1.2 Formål... 3 1.3 Overordnede krav... 3 2 Ressourcer i OS-API et... 4 2.1 Tråde... 4 2.2 Timere... 5 2.3 Semaforer... 5 2.3.1 Binære Semaforer... 5 2.3.2 Tællesemaforer... 5 2.3.3 Mutexer... 6 2.4 Mailboxe... 6 3 Eksempler... 7 3.1 Thread-wrapper til Windows... 7 Revisionshistorie Revision Dato/Initialer Ændring 1.0 051130/TFJ Indledende revision 1.1 051213/TFJ Ændret efter MUP-møde 051212 1.2 060122/TFJ Thread::start() tilføjet 1.3 060306/TFJ Thread::start() tilføjet i eksempel 1.4 060726/TFJ Ændret ifm. udfasning af RTKernel 1.5 061006/TFJ Monitor fjernet. Binære semaforer, tællesemaforer og mutexes indført 1.6 080303/TFJ Småfejl rettet 1.7 010309 Småfejl rettet Side 2 af 8
1 Indledning 1.1 Introduktion Denne note specificerer et abstrakt, objekt-orienteret Operativsystem-Application Programmer s Interface (OS API) implementeret som en række klasser der wrapper de mest almindelige OS-ressourcer. Disse klasser kaldes herefter wrappers. OS-API et er implementeret for Microsoft Windows XP (win32) og Wind River VxWorks 6.x. Wrappers til andre operativsystemer bør overholde det specificerede interface. Noten beskæftiger sig udelukkende med specifikationen af OS-API et. Det forudsættes at læseren er bekendt med de wrappede OS-ressourcer, og er bekendt med deres funktion (sikring af udelelig adgang etc.). 1.2 Formål Formålet med et abstrakt, objektorienteret OS-API er primært: At stille et OO-interface til de mest almindelige OS-resourcer til rådighed og dermed tillade en pæn overgang mellem designet og implementationen af et flertrådet system udviklet med OO-metoder At give et rent snit til OS- ressourcer, så undervisning i brug af et OS kan fokusere på den generelle anvendelse og ikke på et OS-specifik implementation af ressourcer At tillade en let overgang fra et OS til et andet og dermed tillade kørsel af en applikation skrevet til OS-API et at køre på flere forskellige platforme med et minimum af ændringer ideelt set uden ændringer. 1.3 Overordnede krav Formålene stillet op i 1.2 giver anledning til følgende overordnede krav til OS-API et: OS-API et skal implementeres som klasser OS-API et skal fokusere på forståelighed og læsbarhed, om nødvendigt på bekostning af funktionalitet. Det må samtidig ikke blive så abstrakt at typisk OS-opførsel indkapsles. OS-API et skal indkapsle OS et på en sådan måde, at der kun er brug for et minimum af OS-specifik applikationskode, såsom bootstrapping og anden initiering. Side 3 af 8
2 Ressourcer i OS-API et Følgende ressourcer stilles til rådighed i OS-API et: Tråde Timere Semaforer (binære, tælle- og mutex er) Mailboxe Specifikationen af de individuelle ressourcer er givet i de følgende afsnit 2.1 Tråde Tråde er wrappet i den abstrakte klasse Thread. Aktive objekter nedarver fra Thread og implementerer run(), som er task-funktionen, typisk indeholdende en uendelig løkke. Klassen har følgende interface: ThreadPriority Enum. Anvendes til specification af et Thread-objekts prioritet ved initiering eller under programafvikling. Specificerer følgende prioriteter: PRIORITY_LOW, PRIORITY_BELOW_NORMAL, PRIORITY_NORMAL, PRIORITY_ABOVE_NORMAL, PRIORITY_HIGH Thread start ~Thread setpriority getpriority getname Constructor. Opretter Thread-objektet med prioritet pri (default PRIORITY_NORMAL) og navnet name (default ). Starter run() skal kaldes explicit efter at objektet er oprettet. Destructor. Sætter Thread-objektets prioritet til pri Returnerer Thread-objektets aktuelle prioritet Returnerer Thread-objektets navn Side 4 af 8
2.2 Timere Simple sleep-timere er wrappet af klassen SleepTimer. Klassen tillader den kaldende tråd at blive suspended i et givet antal millisekunder. Klassen har følgende interface: SleepTimer ~SleepTimer sleep Constructor Destructor Suspender tråden i ms millisekunder 2.3 Semaforer OS API et specificerer tre forskellige typer semaforer: Binære semaforer, tællesemaforer og mutexer. Alle semafortyper implementerer standard semafor-egenskaber. Desuden: Binære semaforer kan haves af en tråd ad gangen. Her gælder specielt, at signalering til en ledig semafor ikke har nogen effekt. Tællesemaforers kan haves af flere tråde ad gangen. Her gælder specielt, at signalering til en ledig semafor vil tælle semaforen én op, og at tage en ledig semafor vil tælle semaforen én ned. Mutexer virker som binære semaforer. Specielt for RT-systemer gælder, at de bør implementere beskyttelse imod trådsynkroniseringsproblemer (priority inversion, task deletion og recursive ressource access). 2.3.1 Binære Semaforer Binære semaforer er wrappet af klassen BinarySemaphore. Klassen har følgende interface: BinarySemaphore ~BinarySemaphore wait signal Constructor. Initierer pr. default semaforen til at være ikke-taget (fuld) Destructor. Standard semafor wait-funktionalitet Standard semafor signal-funktionalitet 2.3.2 Tællesemaforer Tællesemaforer er wrappet af klassen CountingSemaphore. Klassen har følgende interface: CountingSemaphore ~CountingSemaphore wait signal Constructor. Sætter det initielle antal til initcount Destructor. Standard semafor wait-funktionalitet Standard semafor signal-funktionalitet Side 5 af 8
2.3.3 Mutexer Mutexer er wrappet af klassen Mutex.. Klassen har følgende interface: Mutex ~Mutex wait signal Constructor. Initierer Mutex-objektet Destructor. Nedlægger Mutex-objektet Standard Mutex wait-funktionalitet Standard Mutex signal-funktionalitet 2.4 Mailboxe Mailboxe er wrappet af klassen Mailbox., en parametriseret klasse som tillader overførsel af objekter med statisk størrelse mellem to brugere. Klassen har følgende interface: Mailbox ~Mailbox put get Constructor. Opretter et Mailbox-objekt med plads til cap objekter Destructor. Nedlægger Mailbox-objektet Tilføjer et Item-objekt til mailboxen Returnerer et Item-objekt fra mailboxen Side 6 af 8
3 Eksempler I dette afsnit gives eksempler på hvordan wrappers kan implementeres. 3.1 Thread-wrapper til Windows Thread.h #pragma once #include<windows.h> #include<string> using namespace std; //-------------------------------------------------- // T H R E A D //-------------------------------------------------- class Thread public: // Thread priorities enum ThreadPriority PRIORITY_LOW = THREAD_PRIORITY_LOWEST, PRIORITY_BELOW_NORMAL = THREAD_PRIORITY_BELOW_NORMAL, PRIORITY_NORMAL = THREAD_PRIORITY_NORMAL, PRIORITY_ABOVE_NORMAL = THREAD_PRIORITY_ABOVE_NORMAL, PRIORITY_HIGH = THREAD_PRIORITY_HIGHEST, ; Thread(ThreadPriority pri = Thread::PRIORITY_NORMAL, string _name = ""); ~Thread(); bool setpriority(threadpriority pri); ThreadPriority getpriority(); string getname(); virtual void run() = 0; private: ThreadPriority priority; string name; HANDLE handle; static DWORD WINAPI threadmapper(void* p) ((Thread*)p)->run(); return 0; ; Side 7 af 8
Thread.cpp #include"thread.h" // NAME: Thread // FUNC: Thread::Thread(ThreadPriority pri, string _name) : priority(pri), name(_name) // NAME: ~Thread() // FUNC: Thread::~Thread() // NAME: start() // FUNC: Creates the thread. void Thread::start() handle = CreateThread(NULL, 0, threadmapper,(void*) this, 0, NULL); SetThreadPriority(handle, priority); // NAME: getname() // FUNC: string Thread::getName() return name; // NAME: setpriority // FUNC: Attempts to change the Thread's priority to pri. // RET: true if successful, false otherwise bool Thread::setPriority(ThreadPriority pri) priority = pri; if(setthreadpriority(handle, priority) == 0) return true; else return false; // NAME: getpriority // FUNC: Thread::ThreadPriority Thread::getPriority() return priority; Side 8 af 8