510 likes | 658 Views
Vorlesung Echtzeitbetriebssysteme V. Dr.-Ing. Frank Golatowski. Ziele der Vorlesung. Überblick verschaffen, welche Spezifikation der POSIX-Standard umfasst. Einordnung der Standards 1003.1a bis c. POSIX-Profile kennen lernen. API-Funktionalität vorstellen. Gliederung. POSIX Standards.
E N D
VorlesungEchtzeitbetriebssysteme V. Dr.-Ing. Frank Golatowski
Ziele der Vorlesung • Überblick verschaffen, welche Spezifikation der POSIX-Standard umfasst. • Einordnung der Standards 1003.1a bis c. • POSIX-Profile kennen lernen. • API-Funktionalität vorstellen.
POSIX Standards • Portable Operating System Interface (into a uniX like kernel) • Familie von Standards • Entwickelt durch die IEEE und • IEEE: The Institute of Electrical and Electronics Engineers • Adopted by ISO/IEC • ISO: International Organization for Standardization • IEC: International Electrotechnical Commission • Naming convention • POSIX.x • POSIX-Part x • IEEE Std 1003.x-yyyy yyyy • P1003.x -yyyy yyyy • ISO/IEC 9945-x: yyyy yyyy Eagleeye: Behörden in den USA verlangen bei Rechnerkauf, dass die Software eine POSIX-Schnittstelle hat -> Aus diesem Grund gibt es das Posix-Sub-System unter Windows
POSIX Komponenten • POSIX-Part 1: System Application Program Interface • POSIX.1, POSIX.1b, POSIX.1c, and etc. • POSIX-Part 2: Shell and Utilities • POSIX.2, POSIX.2a, POSIX.21, and etc. • POSIX-Part 3: System Administration • Under development • P1003.5-1992 • Ada Language Interfaces: Binding for System API • P1003.13-1998 • Realtime System Profile
POSIX-Teil 1: System Application Program Interface • POSIX.1 (1990) • POSIX.1b (1993) (called POSIX.4 under developing process) • Echtzeit- Erweiterungen • POSIX.1i (1995) • Technische Berichtigungen zu den Echtzeit- Erweiterungen • POSIX.1c (1995) (called POSIX.4a under developing process) • Thread (Pthreads) • ISO/IEC 9945-1: 1996 (IEEE Std 1003.1-1996) • POSIX.1 + POSIX.1b + POSIX.1c + POSIX.1i • POSIX.1d (1999) • Zusätzliche Echtzeit- Erweiterungen • POSIX.1j (2000) • Ergänzungen zu den Echtzeit- Erweiterungen
IEEE Std 1003.1-1996 • Process Primitives • Process creation/termination, signals • Process Environment • Files and Directories • Input and Output Primitives • Language-Specific Services for the C Programming Language • Libc library • Synchronization • semaphore, mutex, and condition variable
IEEE Std 1003.1-1996 • Memory Management • Execution Scheduling • Fixed priority scheduling • Clocks and Timers • Message Passing • Thread Management / Thread-Specific Data / Thread Cancellation
POSIX.1b (Realtime Extension) Service Flag Bemerkungen Real-time Signal _POSIX_REALTIME_SIGNALS sigwait() (synchronous signal) sigqueue() signotify Input und Output Primitiven _POSIX_SYNCHRONIZED _IO _POSIX_FSYNC _POSIX_AYNCHRONOUS _POSIX_PRIORIZED_IO Synchronisation _POSIX_SEMAPHORES Benannte und memory-based Semaphore Memory Management _POSIX_MEMLOCK _POSIX_MEMLOCK_RANGE _POSIX_MEMORY_PROTECTION_POSIX_MAPPED_FILES _POSIX_SHARED_MEMORY_OBJECTS Scheduling _POSIX_PRIORITY_SCHEDULING SCHED_FIFO SCHED_RR SCHED_OTHER Clocks und Timers _POSIX_TIMERS One shot und periodische Timer, nanosleep() Message Passing _POSIX_MESSAGE_PASSING Message queue Message notification
POSIX.1c (Posix Threads) Synchronisation _POSIX_THREADS _POSIX_THREAD_PROCESS_SHARED Mutex Condition Variable Scheduling _POSIX_THREADPRIORITY_ SCHEDULING _POSIX_THREADPRIO_INHERIT _POSIX_THREAD_PRIO_PROTECT Thread Managment _POSIX_THREADS _POSIX_THREADS_ATTR_STACKADR _POSIX_THREADS_ATTR_STACKSIZE Thread: create, exit, join, detach, etc. Thread Specific Data _POSIX_THREADS Thread Cancellation _POSIX_THREADS Multi-thread Safeness _POSIX_THREADS_SAFE_FUNCTIONS
P1003.13-1998Realtime System Profiles • Originaltitel • Standardized Application Environment Profile POSIX Realtime Application Support (AEP) • Gegenstand sind Eigenschaften verschiedener kommerziell erfolgreicher Realtime-Kerne • pSOS, VRTX32, and VxWorks • Abkürzung • PSE: Generic (System) Environment Profiles • PSE5: Realtime Environments • PSE51: Minimal Realtime System Profile • PSE52: Realtime Controller System Profile • PSE53: Dedicated Realtime System Profile • PSE54: Multi-Purpose Realtime System Profile
Realtime System Profile(PSE51) • System Modell • Systeme, die bestimmt sind für die unbeaufsichtigte Steuerung eines oder mehrerer I/O Geräte. • Keine Interaktion mit Nutzer. Kein Filesystem. • Programmiermodell • Ein einzelner POSIX Prozess enthält ein oder mehrere Threads (threads of control (POSIX.1c threads)). • Spezielle Geräte werden mittels memory mapped I/O oder I/O mapped gesteuert • Hardwaremodell • Ein einzelner Prozessor mit Speicher, aber ohne MMU oder andere übliche I/O-Geräte. • Wenn es mehrere Prozessoren gibt, • mehrere Instanzen des Betriebssystems, die über shared memory oder einem Rückwandbus (backplane channel) kommunizieren
Realtime Controller System Profile(PSE52) • System / Programmiermodell • Erweiterung zu PSE51 • Unterstützung für Dateisystem und asynchrone (nicht blockierende) I/O Interfaces • Hardware Modell • ein Prozessor und Speicher (MMU ist nicht erforderlich). • Keine Massenspeicher erforderlich • Das Dateisystem kann im Speicher (RAM Disk) implementiert sein.
Dedicated Realtime System Profile (PSE53) • System / Programmiermodell • Erweiterung zu PSE51 • Unterstützung mehrerer Prozesse • Einheitliches Interface für Gerätetreiber und Files, aber kein hierachisches Datei system • Memory locking • Hardwaremodell • Ein oder mehrere Prozessoren mit oder ohne MMUs im selben System
Multi-Purpose Realtime System Profile(PSE54) • System / Programmiermodell • Das System unterstützt einen Mix aus real-time and non-real-time Tasks und einigen interaktiven Usertasks • Umfassende Funktionalität • Alles aus POSIX.1, POSIX.1b, und POSIX.1c • Interaktive Sessions (alles aus POSIX.2 und POSIX.2a) • Multi-tasking kann mittels Threads (POSIX.1c threads), Prozessen oder beidem durchgeführt werden. • Unterstützung für „multi-threaded“ Prozesse • Hardwaremodell • Ein oder mehrere Prozessoren mit MMU (memory management units), schnelle Massenspeichern, speziellen Interfaces, Netzwerkunterstützung und Anzeigegeräten (display devices).
POSIX.1 Requirements PSE51 PSE52 PSE53 PSE54 POSIX_SINGLE_PROCESS X X X X POSIX_MULTI_PROCESS - - X X POSIX_SIGNALS X X X X POSIX_USER_GROUPS - - - X POSIX_FILE_SYSTEM - X - X POSIX_FILE_ATTRIBUTES - - - X POSIX_FIFO - - - X POSIX_DEVICE_IO X X X X POSIX_FD_MGMT - X X X POSIX_PIPE - - X X POSIX_DEVICE_SPECIFIC - - - X POSIX_SYSTEM_DATABASE - - - X POSIX_C_LANG_SUPPORT X X X X POSIX_ADA_LANG_SUPPORT X X X X PSE51 PSE52 PSE53 PSE54 _POSIX_JOB_CONTROL X - - X _POSIX_SAVED_IDS - - - X _POSIX_CHOWN_RESTRICTED - - - X _POSIX_NO_TRUNC X X X X _POSIX_VDISABLE - - - X NGROUPS_MAX - - - >=8
POSIX.1b Requirements PSE51 PSE52 PSE53 PSE54 _POSIX_FSYNC X X X X _POSIX_MAPPED_FILES - X - X _POSIX_MEMLOCK X X X X _POSIX_MEMLOCK_RANGE X X X X _POSIX_MEMORY_PROTECTION - - X X _POSIX_PRIORITY_SCHEDULING - - X X _POSIX_SEMAPHORES X X X X _POSIX_SHARED_MEMORY_OBJECTS X X X X _POSIX_REALTIME_SIGNALS X X X X _POSIX_TIMERS X X X X _POSIX_MESSAGE_PASSING X X X X _POSIX_SYNCHRONIZED_IO X X X X _POSIX_ASYNCHRONOUS_IO - X X X _POSIX_PRIORITIZED_IO - - X X
POSIX.1c Requirements PSE51 PSE52 PSE53 PSE54 POSIX_USER_GROUPS_R - - - X POSIX_DEVICE_SPECIFIC_R - - - X POSIX_FILE_LOCKING X X X X POSIX_C_LANG_SUPPORT_R X X X X POSIX_SYSTEM_DATABASE_R - - - X Option PSE51 PSE52 PSE53 PSE54 _POSIX_THREADS X X X X _POSIX_THREAD_ATTR_STACKSIZE - - X X _POSIX_THREAD_PRIO_INHERIT X X X X _POSIX_THREAD_PRIORITY_SCHEDULING - - - X _POSIX_THREAD_PRIO_PROTECT - X - X _POSIX_ THREAD_PROCESS_SHARED - - - X _POSIX_THREAD_ATTR_STACKADDR - - - X
Pthreads (POSIX.1c) • Thread management • Basic primitives • Thread attributes • Execution Scheduling • Synchronization • Mutex • Condition variable • Thread Specific data • ...
Thread Management:Basic Primitives int pthread_create(pthread_t * thread ,const pthread_attr_t * attr ,void * (* start_routine)(void *) ,void * arg); void pthread_exit(void * value_ptr); pthread_t pthread_self(void); int pthread_equal(pthread_t t1, pthread_t t2); • Attr Struktur vorher erläutern? • Hinweis, dass Synchronisation zwischen Threads unbedingt beachtet werden muss • Thread erzeugen
Thread Management:Basic Primitives Was wird hier „gejoined“? • Join & detach • int pthread_join(pthread_t thread, void ** status); • int pthread_detach(pthread_t thread);
Beispiel #include <stdio.h> #include <pthread.h> void Worker(int *idp) { int i; for (i = 0; i < 4; i++) printf("thread %d %dth iteration\n",*idp, i); pthread_exit(0); } void main() { int i; pthread_t threads[3]; int thread_ids[3] = {0,1,2}; for( i = 0 ; i < 3 ; i++ ) pthread_create(&threads[i], NULL , (void *) Worker, &thread_ids[i]); for( i = 0 ; i < 3 ; i++ ) pthread_join(threads[i], NULL); pthread_exit(0); }
Thread Management:Thread Attribute int pthread_attr_init(pthread_attr_t * attr); int pthread_attr_destroy(pthread_attr_t * attr); int pthread_attr_setstacksize(pthread_attr_t * attr, size_t size); int pthread_attr_getstacksize(pthread_attr_t * attr, size_t * size); //PTHREAD_STACK_MIN, PTHREAD_STACK_DEFAULT int pthread_attr_setstackaddr(pthread_attr_t * attr, void * stackaddr); int pthread_attr_getstackaddr(pthread_attr_t * attr, void ** stackaddr); int pthread_attr_setdetachstate(pthread_attr_t * attr, int joinstate); int pthread_attr_getdetachstate(pthread_attr_t * attr, int * joinstate); //PTHREAD_CREATE_JOINABLE, PTHREAD_CREATE_DETACHED int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit); int pthread_attr_getinheritsched(pthread_attr_t *attr, int * inherit); //PTHREAD_INHERIT_SCHED, PTHREAD_EXPLICIT_SCHED int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); int pthread_attr_getschedpolicy(pthread_attr_t * attr, int * policy); //SCHED_RR, SCHED_FIFO, SCHED_OTHER
Execution Scheduling The pthread_getschedparam() and pthread_setschedparam() allow the scheduling policy and scheduling parameters of individual threads within a multi-threaded process to be retrieved and set. For SCHED_FIFO and SCHED_RR, the only required member of the sched_param structure is the priority sched_priority. For SCHED_OTHER, the affected scheduling parameters are implementation-dependent. http://www.rtlinux.org/documents/documentation/man_pages/susv2/xsh/pthread_getschedparam.html Daraus geht hervor, dass es auch andere Scheduler geben kann und demnach die Struktur sched_param flexibel bzw. von policy abhängt • Static scheduling parameter int pthread_attr_setschedparam(pthread_attr_t * attr , struct sched_param * param); int pthread_attr_getschedparam(pthread_attr_t * attr , struct sched_param * param); Kann nur vom Main-Thread aufgerufen werden • Dynamic scheduling parameter int pthread_getschedparam(pthread_t thread, int * policy, struct sched_param *param); int pthread_setschedparam(pthread_t thread, int policy, struct sched_param * param); Eagleeye: Kann von Vater und Sohn-Thread aufgerufen werden struct sched_param { int sched_priority; };
Beispiel #include <stdio.h> #include <pthread.h> void Worker(int *idp) { int i; for (i = 0; i < 4; i++) printf("thread %d %dth iteration\n",*idp, i); pthread_exit(0); } void main() { int i; pthread_t threads[3]; pthread_attr_t thread_attrs; int thread_ids[3] = {0,1,2}; for( i = 0 ; i < 3 ; i++ ) { pthread_attr_init(&thread_attrs); pthread_attr_setschedpolicy(&thread_attrs, SCHED_FIFO); pthread_attr_getschedparam(&thread_attrs, ¶m); param.sched_priority = PTHREAD_MAX_PRIORITY; // 254 pthread_attr_setschedparam(&thread_attrs, ¶m); pthread_create(&threads[i],&thread_attrs,(void *) Worker,&thread_ids[i]); } pthread_exit(0); }
Pthreads (POSIX.1c) • Thread management • Basic primitives • Thread attributes • Execution Scheduling • Synchronization • Mutex • Condition variable • Thread Specific data • ... Wo sind die Semaphoren? Mutex sind binäre Semaphore? Zählende Semaphore muss man sich mit Conditions selber bauen.
Mutex Primitives int pthread_mutex_init(pthread_mutex_t * mutex , const pthread_mutexattr_t * attr); PTHREAD_MUTEX_INITIALIZER int pthread_mutex_destroy(pthread_mutex_t * mutex); int pthread_mutex_lock(pthread_mutex_t * mutex); int pthread_mutex_unlock(pthread_mutex_t * mutex); int pthread_mutex_trylock(pthread_mutex_t * mutex); int pthread_mutex_setprioceiling(pthread_mutex_t * mutex , int prioceiling, int * old_ceiling); int pthread_mutex_getprioceiling(pthread_mutex_t * mutex , int * ceiling);
Pthreads (POSIX.1c) • Thread management • Basic primitives • Thread attributes • Execution Scheduling • Synchronization • Mutex • Condition variable • Thread Specific data • ...
Mutex Attributes int pthread_mutexattr_init(pthread_mutexattr_t * attr); int pthread_mutexattr_destroy(pthread_mutexattr_t * attr); int pthread_mutexattr_setprotocol(pthread_mutexattr_t * attr , int protocol); int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * attr, int * protocol); //PTHREAD_PRIO_NONE, PTHREAD_PRIO_PROTECT, PTHREAD_PRIO_INHERIT int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * attr, int prioceiling); int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * attr, int * ceiling); int pthread_mutexattr_setpshared(pthread_mutexattr_t * attr , int pshared); int pthread_mutexattr_getpshared(const pthread_mutexattr_t * attr , int * pshared); //PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED
Beispiel Dynamische Initialisierung Statische Initialisierung void Thread1(void *data); ... pthread_t thread_id1; ... pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ... void main(void){ ... pthread_create(&thread_id1, ...); ...} void Thread1(void *data){ while(1) { ... pthread_mutex_lock(&mutex); ... pthread_mutex_unlock(&mutex); ... } } void Thread1(void *data); ... pthread_t thread_id1; ... pthread_mutex_t mutex; void main(void){ ... pthread_mutex_init(&mutex, NULL); ... pthread_create(&thread_id1, ...); ... }
Beispiel (2/2) • Ex3: mutex attribute usage void Thread1(void *data); ... pthread_t thread_id1; ... pthread_mutex_t mutex; pthread_mutexattr_t mutex_attr; ... void main(void){ .. pthread_mutexattr_init(&mutex_attr); pthread_mutexattr_setprotocol(&mutex_attr,PTHREAD_PRIO_PROTECT); pthread_mutexattr_setprioceiling(&mutex_attr,0); pthread_mutex_init(&mutex, &mutex_attr); ... pthread_create(&thread_id1, NULL, (void *)Thread1, 0); ... }
Condition Variable int pthread_condattr_init(pthread_condattr_t * attr); int pthread_condattr_destroy(pthread_condattr_t *attr); int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t *attr); //PTHREAD_COND_INITIALIZER int pthread_cond_destroy(pthread_cond_t * cond); int pthread_cond_broadcast(pthread_cond_t * cond); int pthread_cond_signal(pthread_cond_t * cond); int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex); int pthread_cond_timedwait(pthread_cond_t * cond ,pthread_mutex_t * mutex ,const struct timespec * abstime); int pthread_condattr_setpshared(pthread_mutexattr_t *attr, int pshared); int pthread_condattr_getpshared(const pthread_mutexattr_t * attr , int *pshared); //PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED typedef struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ } timespec_t; typedef long time_t;
Beispiel ... pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t count_threshold_cv = PTHREAD_COND_INITIALIZER; void main(void) { int i; pthread_t threads[3]; pthread_create( &threads[0] ,NULL,(void *) inc_count ,&thread_ids[0]); pthread_create( &threads[1] ,NULL,(void *) inc_count ,&thread_ids[1]); pthread_create( &threads[2] ,NULL,(void *) watch_count ,&thread_ids[2]); for( i = 0; i < 3; i++) pthread_join(threads[i], (void **)NULL); pthread_exit(0); } void watch_count(int *idp) { timespec_t abstime = {1,0}; // 1 sec pthread_mutex_lock(&count_mutex); pthread_cond_timedwait( &count_threshold_cv, &count_mutex, &abstime); printf("watch_count(): Thread %d, Count is %d\n",*idp,count); pthread_mutex_unlock(&count_mutex); } void inc_count(int *idp) { int i; for(i =0; i < TCOUNT; i++) { pthread_mutex_lock(&count_mutex); count++; printf("inc_counter(): Thread %d, new count %d\n",*idp, count); if (count == WATCH_COUNT) pthread_cond_signal(&count_threshold_cv); pthread_mutex_unlock(&count_mutex); } }
Thread Specific Data int pthread_key_create(pthread_key_t * key, void (* destructor)(void *)); int pthread_key_delete(pthread_key_t key); int pthread_setspecific(pthread_key_tkey, const void *value); void *pthread_getspecific(pthread_key_t key); ThreadOnce-Execution int pthread_once(pthread_once_t * once_control, void (* init_routine)(void)); PTHREAD_ONCE_INIT
Beispiel static void make_key(void) { (void)pthread_key_create(&key, NULL); } void func(void) { void *ptr; pthread_once(&key_once, make_key); if((ptr = pthread_getspecific(key)) == NULL) { ptr = malloc(OBJECT_SIZE); pthread_setspecific(key, ptr); ... } ... }
Execution Scheduling • Threadbeendigung (Thread cancellation) int pthread_cancel(pthread_t thread); int pthread_setcancelstate(int state, int * oldstate); int pthread_setcanceltype(int type, int * oldtype); // PTHREAD_CANCEL_DEFFERED, PTHREAD_CANCEL_ASYNCHRONOUS void pthread_testcancel(void); void pthread_cleanup_push(void (* routine)(void *), void * args); void pthread_cleanup_pop(int execute); • Prozesserzeugung int pthread_atfork(void (* prepare)(void), void (* parent)(void), void (* child)(void)); • Signal int pthread_kill(pthread_t thread, int sig); int pthread_sigmask(int how, const sigset_t * set, sigset_t * oset);
Probleme • Periodische Ausführung in POSIX • Standard der POSIX-Erweiterung
Periodische Ausführung in POSIX 1/1 • Verwendung von sleep() • Ad-hoc Methode periodic_thread(void* data) { time_t t1, t2; while(1) { time(&t1); /* do something */ time(&t2); if((t2 -t1)>deadline){ /* handle deadline miss */ } sleep(period-(t2-t1)); } } Overhead Späte Behandlung verpasster Deadlines Eagleeye: Den Source versteh ich nicht. Müssen wir mal drüber snacken.
Periodische Ausführung in POSIX 2/2 Eagleeye: Run-time Overhead? Wo, in der Waitroutine? Wie könnte es schneller gehen? Eagleeye: Vorteil: Lokale Variablen müssen nicht bei jedem Thread-Start neu angelegt werden. (Verhinderung von Exceptions, Schnellere Programmabarbeitung) • Periodischer Timer • Thread • Erzeugung eines neuen Threads. Am Ende des Threads wird dieser schlafen gelegt • Problem: • Run-time Overhead • Signal • Ein Signal wird einem Thread zugewiesen und periodisch aktiviert • Problem • Verwendung von Signalen in Multithreaded Umgebung erfordert komplexe und wohl durchdachte Programmierung • Grundlegender Blick auf Signale in POSIX • POSIX unterscheidet Registrierung und Übergabe von Signalen. • Ein Signal wird an jeden Thread gesendet, der dieses nicht blockiert. Eagleeye: Wo werden in dem vorangegangenen Beispiel Signale verwendet?
Beispiel struct sigevent { int sigev_notify; /* notification mode */ int sigev_signo; /* signal number */ union sigval sigev_value; /* signal value */ void (*sigev_notify_function)(union sigval); pthread_attr_t *_sigev_notify_attributes; }; /* no notification */ #define SIGEV_NONE 1 /* queued signal notification */ #define SIGEV_SIGNAL 2 /* call back from another thread */ #define SIGEV_THREAD 3 periodic_routine(){ /* ... */} timer_setup() { /* ... */ #ifdef PERIODIC_THREAD event.sigev_notify = SIGEV_THREAD; /* ... */ #else ifdef PERIODIC_SIGNAL event.sigev_notify = SIGEV_SIGNAL; /* ... */ #endif tid = timer_create (CLOCK_REALTIME, &event); timer.it_value = {release_time,0}; //release_time sec. timer.it_interval = {period, 0}; // period sec. timer_settime (tid, 0, &timer, NULL); } Sekunde Nanosekunde 0: relative time TIMER_ABSTIME:absolute time Eagleeye: 2. #endif fehlt
Standard Way of POSIX Extension • Hinzufügen weiterer Mitglieder zur Struktur sched_param • Problem: Mix der Interfaces und möglich Konfusion bei der Nutzung pthread_attr_t thr1_attr; struct sched_param param; pthread_attr_init(&thr1_attr); pthread_attr_getschedparam(&thr1_attr,¶m); param.sched_priority = PTHREAD_MAX_PRIORITY - 1; param.period = period; param.release_time = release_time; param.deadline = deadline; param.dhandler = dhandler; pthread_attr_setschedparam(&thr1_attr,¶m); pthread_attr_setschedpolicy(&thr1_attr,SCHED_POLICY); pthread_create(&thr1_id, &thr1_attr, &thr1,&thr1_arg); Erweiterte Scheduling parameter
Periodische Prozesse unter RT-Linux Anforderungszeitpunkt Periode Sched_delay Freigabe- zeit Initialisierungs- phase Eagleeye: Müssen wir mal diskutieren
Erweiterung des RT-Linux-Schedulers • Beschreibung, RT-Linux (F.G.) • Beschreibung RT-Linux-Scheduler • allgemein • Beschreibung EDF-Scheduler • Erweiterbarkeit • Beschreibung ELLF- Algorithmus • Integration in RT-Linux
RTLinux Scheduler • Stat. Scheduler • Vergabe der Rechenzeit nach Höhe der Priorität • Periodische und nicht-periodische Threads • Unterbrechung von Threads nur durch Threads höherer Priorität möglich • Linux läuft als „Idle-Task“ mit Priorität 0. • Linux Task • Nicht periodischer Echtzeitprozess • Kommunikation mit RT-Processen nur über Shared-Memory bzw. RT-FIFO‘s • Wird benötigt, um RT-Linux zu beenden • Synchronisationsmechanismen • Mutex • Semaphoren • Conditions variables
RT-Scheduler (Auszug) for (t = sched->rtl_tasks; t; t = t->next) { // evaluate expired timers if (test_bit(RTL_THREAD_TIMERARMED, &t->threadflags)) { if (now >= t->resume_time) // start new task ? { clear_bit(RTL_THREAD_TIMERARMED, &t->threadflags); rtl_sigaddset (&t->pending, RTL_SIGNAL_TIMER); // process can be scheduled if (t->period != 0) // process periodically ? { t->resume_time += t->period; // set next start of process while (now >= t->resume_time) { t->resume_time += t->period; } } else // unknown deadline { t->resume_time = HRTIME_INFINITY; } } } // and find highest priority runnable task if ((t->pending & ~t->blocked) && (!new_task || (t->sched_param.sched_priority > new_task->sched_param.sched_priority))) { new_task = t; } }
ELLF-Scheduler • Basiert auf LLF-Scheduler • Verhinderung des „Trashings“ -> Schedulerlaufzeit vermindert sich • Erkennen von verpassten Deadlines frühzeitig möglich, so dass Notfallprogramm startbar • Prinzip, grundsätzlich wie LLF mit folgenden Erweiterungen: • Beginnen Threads zu „trashen“, wird der mit der geringsten Deadline gewählt – alle anderen werden ausgeschlossen (excluded). • Alle Threads nehmen am Schedulingprozess teil, zugeteilt werden letztendlich aber nur Threads, die nicht ausgeschlossen sind. • Werden ausgeschlossene Threads ausgewählt, wird der laufende Thread weiterbearbeitet.
Vergleich LLF & ELLF Eagleeye: Gute Prüfungsfrage Warum trasht LLF? LLF-Scheduler -> 12 Taskwechsel ELLF-Scheduler -> 3 Taskwechsel • Vergleich der Scheduler LLF und ELLF unter folgenden Extrembedingungen: 3 Tasks mit Px=Dx=td, Rechenzeit Rx=4. • Die Folge ist ein Trashing bei LLF, das mit der Tickauflösung des Schedulers durchgeführt wird. Deadline P3 P2 P1 t tt td Deadline P3 P2 P1 td t tt