Programmazione RTAI - PowerPoint PPT Presentation

About This Presentation
Title:

Programmazione RTAI

Description:

Programmazione RTAI E.Mumolo, DEEI mumolo_at_units.it Programmazione in RTAI Approccio RTAI: Uno schedulatore Real Time rimpiazza lo schedulatore di Linux Intercetta gli ... – PowerPoint PPT presentation

Number of Views:42
Avg rating:3.0/5.0
Slides: 64
Provided by: Smartac
Category:

less

Transcript and Presenter's Notes

Title: Programmazione RTAI


1
Programmazione RTAI
  • E.Mumolo, DEEI
  • mumolo_at_units.it

2
Programmazione in RTAI
  • Approccio RTAI
  • Uno schedulatore Real Time rimpiazza lo
    schedulatore di Linux
  • Intercetta gli interrupt (time e dispositivi)
  • Esegue il codice di servizio degli interrupt in
    tempo reale
  • Esegue Linux nel tempo rimanente (background)
  • Task in tempo reale moduli di kernel non codice
    Linux
  • ? ogni errore provoca un crash del kernel
  • ? non hanno accesso a funzioni di I/O (terminale,
    disco)
  • ? necessità di una comunicazione kernel/utente
    per I/O
  • I MODULI DEL KERNEL SONO CARICATI DINAMICAMENTE!!
  • insmod
  • rmmod

3
Programmazione in RTAI
  • Codifica in C
  • Ogni modulo del kernel ha unentry point
    (init_module) e un exit point (cleanup_module)
  • In definitiva la struttura utilizza 3 parti
    principali scritte dallutente
  • Funzione che inizializza il sistema, definisce le
    caratteristiche dei vari task e IPC
  • Definizione della funzione real time
  • Funzione che rilascia le risorse

4
Programmazione in RTAI
  • Esempio della funzione di rilascio risorse
  • int cleanup_module(void)
  • //ferma il timer
  • stop_rt_timer()
  • rt_busy_sleep(10000000)
  • //chiude la fifo
  • rtf_destroy(0)
  • //cancella la struttura rt
  • rt_task_delete(hiprio_task)

5
Programmazione in RTAI
  • Primo esempio
  • include ltlinux/kernel.hgt
  • include ltlinux/module.hgt
  • MODULE_LICENSE("GPL")
  • int init_module(void) //entry point
  • printk("Hello world!\n") // printk scrive in
    /var/log/messages
  • return 0
  • void cleanup_module(void) //exit point
  • printk("Goodbye world!\n")
  • return

6
Programmazione in RTAI
  • Compilazione sorgenti
  • usare il Makefile del kernel
  • make f Makefile C ltkernel pathgt MPWD
  • Genera il file ltmodulo.kogt
  • Nel nostro caso
  • EXTRA_CFLAGS -I/usr/realtime/include
    -D_IN_RTAI_
  • obj-m prog1.o
  • all
  • make -C /lib/modules/(shell uname -r)/build
    M(PWD) modules
  • clean
  • make -C /lib/modules/(shell uname -r)/build
    M(PWD) clean
  • Per eseguire il modulo insmod ltmodulo.kogt
  • Per terminare rmmod ltmodulo.kogt

7
Programmazione in RTAI
  • Attenzione (1) printk scrive nel kernel ring
    buffer
  • Il buffer viene scritto periodicamente sul file
    di log /var/log/messages
  • Attenzione (2) printk può non essere
    predicibile rt_printk versione RT
  • Scrive sul kernel Ring buffer. Per
    leggere/cancellare il buffer chiamate di
    sistema
  • syslog, klogctl - read and/or clear kernel
    message ring buffer set console_loglevel
  • comandi Linux
  • tkadmin dump ringbuffer ringbuffer.out
  • In definitiva dmesg cinsmod hello.kodmesgrmmo
    d hello.kodmesg
  • Oppure tail -f /var/log/messages

8
Programmazione in RTAI
  • Definizione di un task (thread in tempo reale)
  • int rt_task_init(RT_TASK task,
    void(rt_thread)(int), int data, int stack_size,
  • int priority, int uso_fpu, void(signal)(void))
  • Attenzione definisce il task, non lesegue!
  • Il task si trova nello stato SUSPENDED
  • Argomenti della funzione
  • Primo argomento descrittore del task
  • Secondo argomento entry point della funzione
  • Terzo argomento un intero passato dal genitore
    al thread
  • Quarto argomento dimensione dello stack
  • Quinto argomento priorità . Da rtai_sched.h
  • define RT_SCHED_HIGHEST_PRIORITY 0
  • define RT_SCHED_LOWEST_PRIORITY 0x3fffFfff
  • define RT_SCHED_LINUX_PRIORITY 0x7fffFfff
  • Sesto argomento flag per luso della fpu
  • Settimo argomento funzione per gestire il
    segnale inviato ogni volta che il thread diventa
    running

9
Programmazione in RTAI
  • Schedulazione in RTAI periodica aperiodica
    (one-shot)
  • Modalità di funzionamento
  • void rt_set_oneshot_mode(void)//imposta lo
    schedulatore
  • I task possono essere eseguiti in istanti
    qualsiasi
  • void rt_set_periodic_mode(void) )//imposta lo
    schedulatore
  • Ogni richiesta non multiplo del periodo viene
    soddisfatta nel periodo di base del timer più
    vicino. È il default.
  • La schedulazione è associata al timer
  • RTIME start_rt_timer(int period)//se aperiodic
    il periodo è ignorato
  • RTIME rt_get_time()//ticks se periodico, TSC se
    aperiodico
  • void stop_rt_timer(void)
  • Esempio
  • rt_set_oneshot_mode() start_rt_timer(1)
  • RTIME Internal count units // misura il tempo
    trascorso in ticks
  • Tempi 1 tick838 ns (timer del PC)
  • Inoltre Time Stamp Clock (TSC) clock del PC

10
Programmazione in RTAI
  • Attivazione timer
  • periodico
  • void rt_set_periodic_mode(void)
  • RTIME start_rt_timer(RTIME period)
  • one-shot
  • void rt_set_oneshot_mode(void)
  • RTIME start_rt_timer(RTIME period)
  • La funzione
  • RTIME nano2counts(int nanoseconds)
  • converte da ns a ticks

11
Programmazione in RTAI
  • Esecuzione di un task in tempo reale due
    modalità
  • Rende un processo RTAI periodico ed avvia la
    prima esecuzione allistante ltstart_timegt
  • int rt_task_make_periodic(RT_TASK task, RTIME
    start_time, RTIME period)
  • Task aperiodico (one shot)
  • esecuzione immediata
  • int rt_task_resume(RT_TASK task)
  • esecuzione ad un istante assoluto start_time
  • int rt_task_make_periodic(RT_TASK task, RTIME
    start_time, RTIME period)
  • //period non usato
  • esecuzione ad un istante relativo start_delay
  • int rt_task_make_periodic_relative_ns (RT_TASK
    task, RTIME start_delay, RTIME period)

12
Programmazione in RTAI
  • In definitiva per creare un task aperiodico
  • rt_set_oneshot_mode() start_rt_timer(1)
  • retval rt_task_init(task, function, 0, 1024,
    RT_SCHED_LOWEST_PRIORITY, 0, 0)
  • retval rt_task_resume(task)
  • Gestione della schedulazione
  • Nel caso di task periodico
  • int rt_task_wait_period(void)
  • sospende lesecuzione del thread corrente fino
    al prossimo periodo
  • Nel caso di task aperiodico
  • int rt_task_yield(void)
  • int rt_task_suspend(RT_TASK task)
  • task_yield Fa assumere al processo chiamante lo
    stato READY
  • task_suspend sospende lesecuzione, che verrà
    ripresa con resume o con make_periodic
  • Programma desempio crea un task aperiodico

13
  • include ltlinux/kernel.hgt / dichiarazioni
    richieste dai moduli del kernel /
  • include ltlinux/module.hgt / dichiarazioni
    richieste dai moduli del kernel /
  • include ltlinux/version.hgt
  • include ltlinux/errno.hgt / EINVAL, ENOMEM /
  • include "rtai.h"
  • include "rtai_sched.h"
  • include ltrtai_sem.hgt
  • MODULE_LICENSE("GPL") static RT_TASK print_task
  • void print_function(long arg)
  • rt_printk("Hello world!\n") return
  • int init_module(void)
  • int retval
  • rt_set_oneshot_mode() start_rt_timer(1)
    //parte lesecuzione
  • retval / crea il tread real time /
  • rt_task_init(print_task, print_function, 0,
    1024, RT_SCHED_LOWEST_PRIORITY, 0, 0)
  • if ( retval ! 0)
  • if (-EINVAL retval) printk("task
    task structure is invalid\n")

14
Programmazione in RTAI
  • Funzioni di utilità per la schedulazione
  • void rt_sleep(RTIME delay)
  • void rt_sleep_until(RTIME time)
  • sospendono il thread in esecuzione e lo mettono
    in stato DELAYED
  • void rt_busy_sleep(int nanosecs)
  • addormenta in thread mandando in loop la CPU per
    il tempo indicato
  • void rt_sched_lock(void)
  • void rt_sched_unlock(void)
  • blocca/sblocca lo schedulatore pe evitare corse
    critiche
  • int rt_get_prio(RT_TASK task)
  • int rt_change_prio(RT_TASK task, int priority
  • determina/setta la priorità di base
  • int rt_get_inher_prio(RT_TASK task)
  • Determina la priorità ereditata a causa
    dellaccesso a risorse condivise (protocolli
    priority inheritance)

15
Programmazione in RTAI
  • Altre funzioni di utilità per la schedulazione
  • int rt_get_task_state(RT_TASK task)
  • RT_TASK rt_whoami(void)
  • int rt_task_use_fpu(RT_TASK task, int
    use_fpu_flag)
  • int rt_task_delete(RT_TASK task)
  • rimuove is task dal sistema

16
Programmazione in RTAI Schedulazione periodica
  • Non cè particolare limite al numero di task
  • I task sono thread condividono lo spazio di
    indirizzamento!! Attenzione alla mutua esclusione
  • Dobbiamo determinare il periodo di base. Il
    periodo dei thread è un multiplo del periodo di
    base
  • Programma desempio
  • setto il timer a 1 ms
  • definisco la funzione
  • schedulazione

17
  • include ltlinux/kernel.hgt
  • include ltlinux/module.hgt
  • include ltlinux/version.hgt
  • include ltlinux/sched.hgt
  • include ltlinux/errno.hgt
  • include ltasm/io.hgt
  • include "rtai.h"
  • include "rtai_sched.h"
  • MODULE_LICENSE("GPL")
  • static RT_TASK sound_task static RT_TASK
    delay_task
  • static RTIME sound_period_ns 1e5 / in
    nanoseconds, -gt 10 kHz /
  • static RTIME delay_period_ns 1e9 / in
    nanoseconds, -gt 1 Hz /
  • define SOUND_PORT 0x61 / indrizzo
    altoparlante /
  • define SOUND_MASK 0x02 / bit da cambiare
    /
  • static int delay_count 2 // condivisa tra i
    due threa onda quadra per altoparlante
  • int init_module(void)
  • RTIME sound_period_count, delay_period_count,
    timer_period_count
  • int retval
  • rt_set_periodic_mode()

18
  • retval //struttura del thread delay
  • rt_task_init(delay_task, delay_function, 0,
    1024, RT_LOWEST_PRIORITY, 0, 0)
  • if (0 ! retval) if (-EINVAL retval)
    printk(errore gia in uso\n")
  • else if (-ENOMEM retval) printk(errore di
    stack\n")
  • else printk(error di inizializzazione\n"
    )
  • return retval
  • retval //esegue il thread sund
  • rt_task_make_periodic(sound_task,
    rt_get_time() sound_period_count,
    sound_period_count)
  • if (0 ! retval) if (-EINVAL retval)
    printk("sound errore\n")
  • else printk("sound errore task\n")
  • return retval
  • retval //esegue il thread delay
  • rt_task_make_periodic(delay_task,
    rt_get_time() delay_period_count,
    delay_period_count)
  • if (0 ! retval) if (-EINVAL retval)
    printk(errore delay \n")
  • else printk("delay task error starting
    task\n")

19
  • void sound_function(int arg)
  • int delay_left delay_count /
    decrementato ad ogni ciclo /
  • unsigned char sound_byte, toggle 0
  • while (1)
  • if (delay_left gt 0) //ritardo restante?
  • delay_left--
  • else
  • sound_byte inb(SOUND_PORT)
  • if (toggle) sound_byte sound_byte
    SOUND_MASK
  • else sound_byte sound_byte
    SOUND_MASK
  • outb(sound_byte, SOUND_PORT)
  • toggle ! toggle
  • delay_left delay_count / ricarico
    il ritardo/
  • rt_task_wait_period()

20
  • void cleanup_module(void)
  • int retval
  • retval rt_task_delete(sound_task)
  • if (0 ! retval)
  • if (-EINVAL retval)
  • / invalid task structure /
  • printk("sound task task structure is
    invalid\n")
  • else
  • printk("sound task error stopping
    task\n")
  • retval rt_task_delete(delay_task)
  • if (0 ! retval)
  • if (-EINVAL retval)
  • / invalid task structure /

21
Programmazione in RTAI
  • Politiche di schedulazione
  • RTAI offre la possibilità di usare le seguenti
    politiche FIFO (default), Round Robin.
  • Abilitazione delle politiche
  • void rt_set_sched_policy(struct rt_task_struct
    task, int policy, int rr_quantum_ns)
  • Politiche RT_SCHED_RR - RT_SCHED_FIFO
  • Esempio 3 task appena creati sono bloccati da
    un semaforo che viene aperto appena possono
    continuare.
  • Ogni task esegue per EXECTIME unità temporali,
    realizzato come seguestarttime
    rt_get_cpu_time_ns()while(rt_get_cpu_time_ns()
    lt (starttime EXECTIME))
  • Vene contato il numero di context switch mediante
    un semaforo

22
Programmazione in RTAI
  • In definitiva, la sched. FIFO si realizza con
    queste istruzioni
  • void func1()
  • void func2()
  • int init_module()
  • rt_set_periodic_mode()
  • rt_task_init(t1,func1,)
  • rt_task_init(t2,func2,)
  • rt_task_make_periodic(t1,start1,periodo1)
  • rt_task_make_periodic(t2,start1,periodo2)
  • NB FIFO può essere facilmente anche RM

23
  • include ltlinux/kernel.hgtinclude
    ltlinux/kernel.hgtinclude ltlinux/module.hgtinclud
    e ltrtai.hgtinclude ltrtai_sched.hgtinclude
    ltrtai_sem.hgtMODULE_LICENSE("GPL")define
    STACK_SIZE 2000define EXECTIME
    400000000define RR_QUANTUM 10000000define
    NTASKS 3define PRIORITY 100static SEM sync,
    RT_TASK tasksNTASKS, int switchesCountNTASKS
    static void fun(long indx) //funzione eseguita
    dai task RTIME starttime, endtime rt_printk
    ("Resume task d (p) on CPU d.\n", indx,
    tasksindx, hard_cpu_id()) rt_sem_wait(sync)
    rt_printk("Task d (p) inizia on CPU d.\n",
    indx, tasksindx, hard_cpu_id())
  • starttime rt_get_cpu_time_ns() //esegue per
    EXECTIME
  • while(rt_get_cpu_time_ns() lt (starttime
    EXECTIME)) endtime rt_get_cpu_time_ns()-startt
    ime //segnala il nr di context
    switch tasksindx.signal 0 rt_printk("Task
    d (p) terminates after d.\n", indx,
    tasksindx,endtime)static void
    signal(void) //esegue quando ce un context
    switch RT_TASK task int i for (i 0 i lt
    NTASKS i) if ((task rt_whoami())
    tasksi) switchesCounti
    rt_printk("Switch al task d (p) on CPU d.\n",
    i, task, hard_cpu_id()) break

24
  • int init_module(void) int i printk("INSMOD
    on CPU d.\n", hard_cpu_id()) rt_sem_init(sync,
    0) rt_set_oneshot_mode() start_rt_timer(1)
    for (i 0 i lt NTASKS i) rt_task_init(t
    asksi, fun, i, STACK_SIZE, PRIORITY, 0,
    signal) for (i 0 i lt NTASKS i)
    rt_task_resume(tasksi) rt_sem_broadcas
    t(sync) return 0void cleanup_module(void)
    int i stop_rt_timer() rt_sem_delete(sync)
    for (i 0 i lt NTASKS i) printk("nr
    di context switches task d -gt d\n", i,
    switchesCounti) rt_task_delete(tasksi)

25
Programmazione in RTAI
  • Schedulazione prioritaria
  • I thread hanno una priorità tra 0
    (RT_SCHED_HIGHEST_PRIORITY) e 1,073,741,823
    (RT_SCHED_LOWEST_PRIORITY )
  • Quando si crea un task con rt_task_init(..)  uno
    degli argomenti è la priorità
  • Dopo che viene eseguito un task può variare
    priorità con int rt_change_prio( RT_TASK task,
    intpriority) 
  • La politica prioritaria è RT_SCHED_FIFO
  • Esempio creazione di 3 task a diverse priorità.
    Provae a cambiare le priorità

26
  • include ltlinux/kernel.hgt
  • include ltlinux/module.hgt
  • include ltrtai.hgt
  • include ltrtai_sched.hgt
  • include ltrtai_sem.hgt
  • MODULE_LICENSE("GPL")
  • define STACK_SIZE 2000
  • define EXECTIME 400000000
  • define RR_QUANTUM 10000000
  • define NTASKS 3
  • define HIGH 100
  • define MID 101
  • define LOW 102
  • static SEM sync, RT_TASK tasksNTASKS, int
    switchesCountNTASKS
  • static void fun(long indx)
  • RTIME starttime, endtime
  • rt_printk("Resume task d (p) on CPU d.\n",
    indx, tasksindx, hard_cpu_id())

27
  • static void signal(void) //per segnalare il nr di
    context switches
  • RT_TASK task
  • int i
  • for (i 0 i lt NTASKS i)
  • if ((task rt_whoami()) tasksi)
  • switchesCounti rt_printk(passa a d
    (p) su d.\n", i, task, hard_cpu_id())
  • break
  • int init_module(void)
  • int i
  • printk("INSMOD on CPU d.\n", hard_cpu_id())
    rt_sem_init(sync, 0)
  • rt_set_oneshot_mode() start_rt_timer(1)
  • rt_task_init(tasks0, fun, 0, STACK_SIZE,
    LOW, 0, signal)
  • rt_task_init(tasks1, fun, 1, STACK_SIZE, MID,
    0, signal)
  • rt_task_init(tasks2, fun, 2, STACK_SIZE,
    HIGH, 0, signal)

28
Programmazione in RTAI
  • Schedulazione RateMonotonic (RM)

29
  • include ltlinux/kernel.hgt / decls needed for
    kernel modules /
  • include ltlinux/module.hgt / decls needed for
    kernel modules /
  • include ltlinux/version.hgt /
    LINUX_VERSION_CODE, KERNEL_VERSION() /
  • include ltlinux/errno.hgt / EINVAL, ENOMEM /
  • include "rtai.h"
  • include "rtai_sched.h"
  • include ltrtai_sem.hgt
  • MODULE_LICENSE("GPL")
  • define NTASKS 3
  • define STACK_SIZE 10000
  • static RT_TASK tasksNTASKS
  • static int task_argNTASKS
  • define BASE_PERIOD_NS 1000000
  • static RTIME base_period // in internal units
  • static RTIME base_period_us // in microseconds
  • static RTIME base_period_ns // in nanoseconds
  • static int task_computation_timeNTASKS 30 ,
    20 , 20 //timer periodici
  • static int task_periodNTASKS 60 ,
    90 , 110
  • static int task_priorityNTASKS 10 ,
    20 , 30

30
  • / function to callibrate busysleep function /
  • void calibrate_busysleep(void)
  • RTIME sleeptime_ns
  • RTIME x
  • volatile RTIME loop_sizeCALIBRATION_LOOP_SIZE
  • // loop with global CALIBRATION_LOOP_SIZE
  • sleeptime_nsloop(loop_size)
  • rt_printk("sleeptime_nslld\n",sleeptime_ns)
  • //
  • // sleeptime_in_us sleeptime_ns/1000
  • // count_need_for_one_us_busysleepcalibrat
    ion_loop_size/sleeptime_in_us
  • // -gt somma fattore di calibrazione
  • // sleeptime_in_us -gt
    sleeptime_in_us calibrationpercentage/100

31
  • //tiene il processore occuato per sleeptime_us,
    ritorna il tempo passato
  • RTIME busysleep(RTIME sleeptime_us )
  • RTIME temp
  • RTIME sleeptime_ns
  • RTIME sleep_count
  • sleep_count count_need_for_one_ms_busysleepslee
    ptime_us
  • do_div(sleep_count,1000)
  • sleeptime_nsloop(sleep_count)
  • return sleeptime_ns
  • // calibrazione della attesa attiva
  • rt_printk("-----------------------------------
    ------- init task started\n",arg)
  • calibrate_busysleep()
  • rt_printk("count_need_for_one_ms_busysleepll
    d\n", count_need_for_one_ms_busysleep)
  • rt_printk("-----------------------------------
    ------- init task ended\n",arg)
  • return

32
  • RTIME get_time() //calcola il tempo di esecuzione
  • RTIME temp
  • temprt_get_time()-tasks_starttime
  • return temp
  • void print_info(int currenttask,char msg)
  • RTIME nowget_time()
  • rt_printk("Td s - time 3lld.02lld -
    computation 3d - period 3d - interval d-d
    \n",currenttask, msg, time_int(now),time_digits(
    now), task_computation_timecurrenttask,
    task_periodcurrenttask, task_period_countercurr
    enttasktask_periodcurrenttask,
    (task_period_countercurrenttask1)task_periodc
    urrenttask)
  • void dummy_task(long t) /calibrazione
  • RTIME cur_task_sleeptime_ns,
    cur_task_sleeptime_us, base_periods_passed,
    cur_task_period
  • cur_task_periodtask_periodtbase_period
  • cur_task_sleeptime_usbase_period_ustask_comp
    utation_timet
  • task_period_countert0 base_periods_passed
    0
  • if (!tasks_starttime) tasks_starttimert_get_time
    ()
  • while( time_int(get_time()) lt ggd
    nodeadlinemiss )
  • resumetimettasks_starttime
    (task_period_countertcur_task_period)

33
  • int init_module(void) //parte il task con
    chedulaione specifica
  • int i
  • RTIME temp,starttime
  • printk(inizia init_module\n")
  • printk("INSMOD on CPU d.\n", hard_cpu_id())
  • rt_sem_init(sync, 0)
  • rt_set_periodic_mode() //configura il modo
  • base_period start_rt_timer(nano2count(BASE_P
    ERIOD_NS))
  • rt_printk("base_period lld.\n\n",base_perio
    d)
  • base_period_nscount2nano(base_period)
  • rt_printk("base_period_ns
    lld.\n\n",base_period_ns)
  • tempbase_period_ns do_div(temp,1000)
    base_period_ustemp
  • // base_period_uscount2nano(base_period)/1000
  • rt_printk("base_period_us
    lld.\n\n",base_period_us)
  • rt_task_init(init_task_str, init, 0,
    STACK_SIZE, 100, 0, 0)

34
  • void cleanup_module(void)
  • int i
  • stop_rt_timer()
  • rt_sem_delete(sync)
  • printk("\n\n")
  • for (i 0 i lt NTASKS i)
  • rt_task_delete(tasksi)
  • rt_task_delete(init_task_str)

35
Schedulazione EarliestDeadlineFirst (EDF)
  • include ltlinux/module.hgt
  • include ltasm/io.hgt
  • include ltasm/rtai.hgt
  • include ltrtai_sched.hgt
  • define ONE_SHOT
  • define TICK_PERIOD 10000000
  • define STACK_SIZE 2000
  • define LOOPS 3
  • define NTASKS 8
  • static RT_TASK threadNTASKS
  • static RTIME tick_period
  • static int cpu_usedNR_RT_CPUS
  • static void fun(long t)
  • unsigned int loops LOOPS
  • while(loops--)
  • cpu_usedhard_cpu_id()

36
EDF (cont.)
  • int init_module(void)
  • RTIME now
  • int i
  • ifdef ONE_SHOT
  • rt_set_oneshot_mode()
  • endif
  • for (i0iltNTASKSi) rt_task_init(threadi,fu
    n,i,STACK_SIZE,NTASKS-i-1,0,0)
  • tick_period start_rt_timer(nano2count(TICK_PERI
    OD))
  • now rt_get_time() NTASKStick_period
  • for (i 0 i lt NTASKS i)
  • rt_task_make_periodic(threadNTASKS - i - 1,
    now, NTASKStick_period)
  • return 0
  • void cleanup_module(void)
  • int i, cpuid
  • stop_rt_timer()

37
Programmazione in RTAI IPC
  • RTAI usa sistemi di IPC simili a Linux ma
    implementati separatamente
  • rt_fifo scambio dati tra i thread in tempo
    reale, tra processi Linux,
  • shared memory, tra thread in tempo reale e
    processi Linux
  • mailbox
  • semafori
  • RPC

38
Programmazione in RTAI IPC
  • rt_fifo
  • Per creare una rt_fifo
  • int rtf_create(unsigned int fifo, int size)
  • Per dimensionare una rt_fifo
  • int rtf_resize(int fd, int size)
  • Per creare/aprire una rt_fifo dallo spazio utente
    si usa
  • file_descriptor open("/dev/rtf0", O_RDONLY)
  • Per creare/aprire una rt_fifo dallo spazio kernel
    si usa
  • int rtf_open_sized(const char dev, int perm, int
    size)
  • Le rt_fifo possono essere associate a dei command
    handler che vanno
  • in esecuzione ogni volta che un processo nello
    spazio utente esegue
  • una read() o una write() sulla fifo
  • int rtf_create_handler(unsigned int minor, int
    (handler)(unsigned int fifo)))

39
Programmazione in RTAI IPC
  • rt_fifo esempio duso dei command handler
  • int rtf_create_handler(fifo_numver,
    X_FIFO_HANDLER(x_handler)
  • con, ad esempio, come x_handler
  • int x_handler(unsigned int fifo, int rw)
  • if(rwr)
  • //quello che bisogna fare in relazione ad una
    read
  • else
  • //quello che bisogna fare in relazione ad una
    write

40
Programmazione in RTAI IPC
  • rt_fifo per evitare bloccaggi indeterminati
  • int rtf_read_all_at_once(int fd, void buf, int
    count)
  • int rtf_read_timed(int fd, void buf, int count,
    int ms_delay)
  • int rtf_write_timed(int fd, void buf, int count,
    int ms_delay)
  • rt_fifo uso dei semafori
  • int rtf_sem_init(unsigned int fifo, int value)
  • int rtf_sem_wait(unsigned int fifo) //solo dallo
    spazio utente
  • int rtf_sem_trywait(unsigned int fifo) //solo
    dallo spazio utente
  • ...

41
Programmazione in RTAI IPC
  • Per accedere una rt_fifo
  • Dal lato real time
  • num_read rtf_get(0, buffer_in,
    sizeof(buffer_in))
  • num_written rtf_put(1, buffer_out,
    sizeof(buffer_out))
  • Dal lato Linux
  • num_read read(read_descriptor, buffer_in,
    sizeof(buffer_in))
  • num_written write(write_descriptor,
    buffer_out,sizeof(buffer_out))
  • Letture bloccanti Unix supporta sia lettura
    bloccanti che non
  • In sistemi real time sono preferibili le letture
    non bloccanti 'rtf_get()' ritorna immediatamente
    se non ci sono dati da leggere

42
  • //FIFO monodirezionali
  • include ltlinux/kernel.hgt / decls needed for
    kernel modules /
  • include ltlinux/module.hgt / decls needed for
    kernel modules /
  • include ltlinux/version.hgt / LINUX_VERSION_CODE,
    KERNEL_VERSION() /
  • include ltlinux/errno.hgt / EINVAL, ENOMEM /
  • include ltrtai.hgt
  • include ltrtai_sched.hgt
  • include ltrtai_fifos.hgt
  • MODULE_LICENSE("GPL")
  • static RT_TASK t1
  • static RT_TASK t2
  • void taskOne(long arg)
  • void taskTwo(long arg)
  • define MAX_MESSAGES 100
  • define MAX_MESSAGE_LENGTH 50

43
  • void taskOne(long arg)
  • int retval
  • char message "Received message from
    taskOne"
  • rt_printk("taskOne starts sending
    message\n")
  • retval rtf_put(0, message,
    sizeof(message)) //trasmette
  • rt_printk("taskOne continues after sending
    message\n")
  • void taskTwo(long arg)
  • int retval
  • char msgBufMAX_MESSAGE_LENGTH
  • rt_printk("taskTwo ready to receive\n")
  • retval rtf_get(0, msgBuf, sizeof(msgBuf))
    //riceve
  • if (retvalgt0)
  • rt_printk("TaskTwo s\n", msgBuf)
    rt_printk(" lunghezza d\n", retval)
  • else printk("FIFO queue is empty\n")

44
  • Altro esempio FIFO bidirezionali
  • include ltlinux/kernel.hgt
  • include ltlinux/module.hgt
  • include ltlinux/version.hgt
  • include ltlinux/errno.hgt
  • include ltrtai.hgt
  • include ltrtai_sched.hgt
  • include ltrtai_fifos.hgt
  • MODULE_LICENSE("GPL")
  • static RT_TASK t1
  • static RT_TASK t2
  • void taskOne(long arg)
  • void taskTwo(long arg)
  • define MAX_MESSAGES 100
  • define MAX_MESSAGE_LENGTH 50
  • static RTIME delay_count, delay_ns 1e6 / in
    nanoseconds, -gt 1 msec /
  • void message(void) / function to create the
    message queue and two tasks /

45
  • void taskOne(long arg)
  • int retval0 char message Messaggio
    dal taskOne"
  • char msgBufMAX_MESSAGE_LENGTH
    msgBuf00
  • rt_printk("taskOne inizia a mandare un
    messaggio al taskTwo via FIFO\n")
  • retval rtf_put(2, message,
    sizeof(message)) //manda messaggio a taskTwo
  • rt_printk("taskOne continua\n")
  • t_sleep(delay_count) //aspetta per far partire
    taskTwo
  • retval rtf_get(1, msgBuf, sizeof(msgBuf))
    //riceve il messaggio
  • if ( retval lt 0 ) rt_printk("problem with
    fifo \n") //test cambia id in rtf_get
  • else rt_printk("taskOne riceve s con
    lunghezza d \n", msgBuf, retval)
  • void taskTwo(long arg)
  • int retval0 char msgBufMAX_MESSAGE_LENGTH
  • char message " Messaggio dal taskTwo "
    msgBuf00

46
  • int init_module(void)
  • printk("start of init_module\n")
  • message()
  • printk("end of init_module\n")
  • return 0
  • void cleanup_module(void)
  • stop_rt_timer()
  • rt_task_delete(t1)
  • rt_task_delete(t2)
  • return

47
Programmazione in RTAI IPC
  • Mailbox è un buffer gestito dal SO per scambio
    di messaggi tra processi e task
  • Possono essere inizializzati per messaggi di
    lunghezza variabile
  • Supportano più lettori/scrittori su base
    prioritaria
  • Gestione prioritaria un task che invia può
    essere interrotto se il task che aspetta è a
    priorità più alta
  • Usabili dallo spazio utente e dallo spazio kernel
  • Possono sostituire le rt_fifo ma sono più lente
  • Implementate nello schedulatore di RTAI
  • Invio e ricezione di messaggi
  • Incondizionato
  • Su un certo numero di byte
  • Con scadenza relativa/assoluta
  • Per inizializzare/creare (messaggi di lunghezza
    arbitraria)
  • int rt_mbx_init(MBX mbx, int size)//size del
    buffer
  • Inizializzare/creare una mailbox tipizzata
  • int rt_typed_mbx_init(MBX mbx, int size, int
    type)

48
Programmazione in RTAI IPC
  • Mailbox per inviare/ricevere dati senza/con
    condizioni
  • int rt_mbx_send(MBX mbx, int size)
  • int rt_mbx_receive(MBX mbx, int size)
  • int rt_mbx_send_wp(MBX mbx, int size)
  • int rt_mbx_receive_wp(MBX mbx, int size)
  • int rt_mbx_send_if(MBX mbx, int size)
  • int rt_mbx_receive_if(MBX mbx, int size)
  • Programma desempio taskOne manda un messaggio
    via mailbox a taskTwo che lo scrive

49
  • include ltlinux/kernel.hgt / decls needed
    for kernel modules /
  • include ltlinux/module.hgt / decls needed
    for kernel modules /
  • include ltlinux/version.hgt /
    LINUX_VERSION_CODE, KERNEL_VERSION() /
  • include ltlinux/errno.hgt / EINVAL, ENOMEM
    /
  • include ltrtai.hgt
  • include ltrtai_sched.hgt
  • include ltrtai_mbx.hgt
  • MODULE_LICENSE("GPL")
  • static RT_TASK t1
  • static RT_TASK t2
  • void taskOne(long arg)
  • void taskTwo(long arg)
  • define MAX_MESSAGES 100
  • define MAX_MESSAGE_LENGTH 50
  • static MBX mailboxId
  • void message(void) / function to create the
    message queue and two tasks /
  • int retval

50
  • void taskOne(long arg) / task che scrive nella
    mailbox /
  • int retval
  • char message ricvuto messaggio da
    TaskOne"
  • retval rt_mbx_send(mailboxId, message,
    sizeof(message)) //spedisce
  • if (0 ! retval)
  • if (-EINVAL retval)
    rt_printk("mailbox invalida\n")
  • else rt_printk(errore sconosciuto\n")
  • else rt_printk("taskOne ha inviato
    messaggio\n")
  • void taskTwo(long arg) / tasks che legge dalla
    mailbox /
  • int retval
  • char msgBufMAX_MESSAGE_LENGTH
  • retval rt_mbx_receive_wp(mailboxId, msgBuf,
    50)
  • if (-EINVAL retval)
    rt_printk("mailbox invalida\n")

51
  • int init_module(void)
  • printk(inizia init_module\n")
  • rt_set_oneshot_mode()
  • start_rt_timer(1)
  • message()
  • printk(finisce init_module\n")
  • return 0
  • void cleanup_module(void)
  • stop_rt_timer()
  • rt_task_delete(t1)
  • rt_task_delete(t2)

52
Programmazione in RTAI IPC
  • IPC memoria condivisa (shared memory)
  • Per trasferire dati tra processi e task
  • Naturalmente sono molto veloci
  • Svantaggi
  • non essendo serializzati necessitano di un
    protocollo di accesso
  • il bloccaggio tra processi e task non è
    supportato ? bisogna gestire il trasferimento con
    un metodo
  • non è garantita la mutua esclusione processi/task
  • Non è possibile rilevare letture/scritture
    interrotte
  • Tipi di shared memory
  • Mbuff condivisione processi/thread (cioè spazio
    utente/spazio kernel) senza richiedere RTAI
  • Shmem condivisione processi/thread (cioè spazio
    utente/spaziokernel) che dipende profondamente da
    RTAI

53
Programmazione in RTAI IPC
  • mbuff
  • Implementata come device driver device
    /dev/mbuff
  • Per accedere alla memoria condivisa dallo spazio
    utente/kernel
  • void mbuff_alloc(unsigned long name, unsigned
    int size)
  • Per rilasciare la memoria
  • void mbuf_free(int name, void mbuf)

54
IPC in RTAI memoria condivisa
  • shmem
  • Implementata come device driver device
    /dev/rtai_shm
  • Per accedere dallo spazio utente
  • void rtai_malloc(unsigned long name, int size)
  • Per rilasciarla
  • void rtai_free(int name, void adr)
  • Per accedere dallo spazio kernel
  • void rtai_malloc(unsigned long name, int size)
  • Per rilasciarla
  • void rtai_free(int name, void adr)

55
IPC in RTAI semafori
  • Semafori sono di tre tipi
  • Counting Usati per registrare eventi (CNT_SEM)
  • Binary Usati per gestire eventi binari (BIN_SEM)
  • Resource Usati per gestire laccesso a risorse
    mediante la priority inheritance (RES_SEM)
  • Per inizializzare un semaforo
  • void rt_typed_sem_init(SEM sem, int value, int
    type)
  • Per usare un semaforo
  • int rt_sem_wait(SEM sem)
  • int rt_sem_signal(SEM sem)
  • Per il test sulla condizione di blocco
  • int rt_sem_wait_if(SEM sem)
  • Per il test sul tempo massimo di blocco
  • int rt_sem_wait_timed(SEM sem, RTIME delay)

56
Programmazione in RTAI
  • Problema della Inversione della priorità

57
  • include ltlinux/kernel.hgt / decls needed for
    kernel modules /
  • include ltlinux/module.hgt / decls needed for
    kernel modules /
  • include ltlinux/version.hgt / LINUX_VERSION_CODE,
    KERNEL_VERSION() /
  • include ltlinux/errno.hgt / EINVAL, ENOMEM /
  • include "rtai.h" / RTAI configuration switches
    /
  • include "rtai_sched.h
  • include ltrtai_sem.hgt
  • MODULE_LICENSE("GPL")
  • define ITER 10
  • define HIGH 102 / high priority /
  • define MEDIUM 103 / medium priority /
  • define LOW 104 / low priority /
  • define NORMAL_TIME 20000000 / nanoseconds /
  • define LONG_TIME 50000000 / nanoseconds /
  • static RT_TASK t1, t2, t3
  • void prioHigh(long arg)
  • void prioMedium(long arg)
  • void prioLow(long arg)
  • static SEM sync, SEM semBinary int global 0

58
  • int init_module(void)
  • printk("start of init_module\n")
  • rt_set_oneshot_mode()
  • start_rt_timer(1)
  • binary()
  • printk("end of init_module\n")
  • return 0
  • void cleanup_module(void)
  • return
  • void prioLow(long arg)
  • RTIME startime
  • int i
  • rt_printk("RESUMED TASK d (p) ON CPU
    d.\n", arg, t3, hard_cpu_id())
  • rt_sem_wait(sync)

59
  • void prioMedium(long arg)
  • RTIME startime
  • int i
  • rt_printk("RESUMED TASK d (p) ON CPU d.\n",
    arg, t2, hard_cpu_id())
  • rt_sem_wait(sync)
  • rt_sleep(nano2count(10000000))/ lascia
    tempo per i thread a bassa priorità /
  • for (i0 i lt ITER i)
  • rt_printk("Medium task running\n")
    startime rt_get_cpu_time_ns()
  • while(rt_get_cpu_time_ns() lt (startime
    LONG_TIME))
  • rt_printk("------------------------------Mediu
    m priority task exited\n")
  • void prioHigh(long arg)
  • RTIME startime
  • int i
  • rt_printk("RESUMED TASK d (p) ON CPU
    d.\n", arg, t1, hard_cpu_id())

60
Programmazione in RTAI
  • Algoritmo priority inversion implementazione in
    RTAI
  • Si risolve con semafori di tipo resource
  • rt_typed_sem_init(semBinary, 1, BIN_SEM FIFO_Q
    )

61
  • include ltlinux/kernel.hgt / decls needed for
    kernel modules /
  • include ltlinux/module.hgt / decls needed for
    kernel modules /
  • include ltlinux/version.hgt / LINUX_VERSION_CODE,
    KERNEL_VERSION() /
  • include ltlinux/errno.hgt / EINVAL, ENOMEM /
  • include "rtai.h" / RTAI configuration switches
    /
  • include "rtai_sched.h"
  • include ltrtai_sem.hgt
  • MODULE_LICENSE("GPL")
  • define ITER 10
  • define HIGH 102 / high priority /
  • define MEDIUM 103 / medium priority /
  • define LOW 104 / low priority /
  • define NORMAL_TIME 20000000 / nanoseconds /
  • define LONG_TIME 50000000 / nanoseconds /
  • static RT_TASK t1, t2, t3
  • void prioHigh(long arg)
  • void prioMedium(long arg)
  • void prioLow(long arg)
  • static SEM sync, SEM semBinary // semafori

62
  • void prioLow(long arg)
  • RTIME startime
  • int i
  • rt_printk("RESUMED TASK d (p) ON CPU d.\n",
    arg, t3, hard_cpu_id())
  • rt_sem_wait(sync)
  • for (i0 i lt ITER i)
  • rt_sem_wait(semBinary)/ wait indefinitely
    for semaphore /
  • rt_printk("Low priority task locks
    semaphore\n")
  • startime rt_get_cpu_time_ns()
  • while(rt_get_cpu_time_ns() lt (startime
    NORMAL_TIME))
  • rt_printk("Low priority task unlocks
    semaphore\n")
  • rt_sem_signal(semBinary) / give up
    semaphore /
  • rt_printk("...................................
    .......Low priority task exited\n")
  • void prioMedium(long arg)

63
  • void prioHigh(long arg)
  • RTIME startime
  • int i
  • rt_printk("RESUMED TASK d (p) ON CPU
    d.\n", arg, t1, hard_cpu_id())
  • rt_sem_wait(sync)
  • rt_sleep(nano2count(30000000))/ lascia
    tempo ai task di piu bassa priorità /
  • for (i0 i lt ITER i)
  • rt_printk("High priority task trys to lock
    semaphore\n")
  • rt_sem_wait(semBinary)/ wait
    indefinitely for semaphore /
  • rt_printk("High priority task locks
    semaphore\n")
  • startime rt_get_cpu_time_ns()
  • while(rt_get_cpu_time_ns() lt (startime
    NORMAL_TIME))
  • rt_printk("High priority task unlocks
    semaphore\n")
  • rt_sem_signal(semBinary) / give up
    semaphore /
  • rt_printk("...................................
    ...High priority task exited\n")
Write a Comment
User Comments (0)
About PowerShow.com