Avanti Indietro Indice

6. Comunicazione inter-processo

Il programma di esempio visto prima è quel che si dice essere un processo realtime. Comunque non occorre che tutte le parti che compongono un applicativo siano scritte per funzionare in realtime. Di solito, solo quelle sezioni che necessitano di temporizzazioni molto precise sono scritte in tale maniera. Le rimamenti possono essere eseguite in user space. Rispetto ai thread realtime, i processi in user space sono spesso più semplici da scrivere ed eseguire ed è più facile farne il debug.

La comunicazione inter-processo può avvenire in diversi modi. Verrà qui discusso solo il più importante e frequentemente usato: i FIFO realtime.

6.1 FIFO realtime

I FIFO realtime sono code unidirezionali (First In First Out). I dati possono essere scritti da un lato e letti dall'altro da processi differenti. Uno dei due è di solito il thread realtime mentre l'altro si trova in user space.

I FIFO realtime sono semplicemente dei character device (/dev/rtf*) con un numero primario pari a 150. I thread realtime usano numeri interi per riferirsi a ciascun FIFO (per esempio il numero 2 per /dev/rtf2). Si noti che esiste un limite per il numero totale di FIFO. I FIFO devono essere gestiti attraverso apposite funzioni come rtf_create(), rtf_destroy(), rtf_get(), rtf_put() e così via.

Per quanto riguarda invece i processi d'utente, essi vedono i FIFO realtime come normali character device. Di conseguenza possono essere usate le solite funzioni come open(), close(), read() e write().

6.2 Un'applicazione che fa uso di FIFO

Consideriamo in primo luogo un semplice programma in C (di nome pcaudio.c) che riproduce musica (semplicemente due note) per mezzo dell'altoparlante del PC. Per il momento si supponga che per suonare una nota si debba semplicemente scrivere sul character device /dev/rtf3. (In seguito vedremo un processo realtime che manda all'altoparlante ciò che legge da tale FIFO (/dev/rtf3)).

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define DELAY 30000

void make_tone1(int fd)
{
        static char buf = 0;
        write (fd, &buf, 1);
}

void make_tone2(int fd)
{
        static char buf = 0xff;
        write (fd, &buf, 1);
}

main()
{
        int i, fd = open ("/dev/rtf3", O_WRONLY);
        while (1)
        {
                for (i=0;i<DELAY;i++);
                make_tone1(fd);
                for (i=0;i<DELAY;i++);
                make_tone2(fd);
        }
}

Ora, se il programma sopra esposto (pcaudio.c) è compilato ed eseguito, esso dovrebbe dar luogo ad una serie di suoni corrispondenti ad un'onda quadra. Tuttavia abbiamo prima bisogno di un modulo che legga da '/dev/rtf3' e mandi i dati corrispondenti all'altoparlante del PC. Questo programma realtime può essere trovato fra i sorgenti di rtlinux (/usr/src/rtlinux/examples/sound/). Inserite il modulo sound.o usando il comando 'insmod'.

Visto che abbiamo caricato il modulo che legge dal device, possiamo a questo punto eseguire il nostro programma (compilatelo usando 'gcc' e lanciate il corrispondente 'a.out'). Il processo produrrà dei toni più o meno regolari, almeno nel caso non ci siano altri (impegnativi) processi nel sistema. Tuttavia, se il server X viene fatto partire da un'altra console, si avvertiranno alcune pause nella riproduzione. Peggio ancora, quando un comando 'find' (per un file sotto la directory /usr) viene eseguito, la serie di suoni diverrà completamente distorta. Il motivo di questo fenomeno risiede nel fatto che non stiamo scrivendo dati nel FIFO in realtime.

Verrà illustrato subito come eseguire il processo in realtime, in maniera tale che il suono sia riprodotto senza alcun tipo di disturbo. In primo luogo, convertiamo il programma precedentemente esposto in un programma realtime (nome del file rtaudio.c).

#include <rtl.h>
#include <pthread.h>
#include <rtl_fifo.h>
#include <time.h>

#define FIFO_NO 3
#define DELAY 30000
pthread_t thread;

void * sound_thread(int fd)
{
        int i;
        static char buf = 0;
        while (1)
        {
                for(i=0; i<DELAY; i++);
                buf = 0xff;
                rtf_put(FIFO_NO, &buf, 1);

                for(i=0;i<DELAY;i++);
                buf = 0x0;
                rtf_put(FIFO_NO, &buf, 1);
        }
        return 0;
}

int init_module(void)
{
        return pthread_create(&thread, NULL, sound_thread, NULL);
}

void cleanup_module(void)
{
        pthread_delete_np(thread);
}

Se non è già stato fatto prima, caricate il modulo sound.o nel kernel. Compilate il programma visto sopra scrivendo un opportuno Makefile (come descritto in precedenza), quindi ricavatene il modulo 'rtaudio.o'. Prima di inserire questo modulo, un ultima avvertenza. Dovreste notare che il programma esegue un ciclo infinito. Visto che non è stato inserito codice per fermare o interrompere il thread, esso non cesserà mai di operare. In parole povere, l'altoparlante del vostro PC continuerà a produrre il tono indefinitivamente fino a quando non riavvierete il vostro computer.

Cambiamo leggermente il codice (solo la funzione sound_thread()) in modo che il thread stesso gestisca il ritardo fra le note.

void * sound_thread(int fd)
{
        static char buf = 0;
        pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000);

        while (1)
        {
                pthread_wait_np();
                buf = (int)buf^0xff;
                rtf_put(FIFO_NO, &buf, 1);
        }
        return 0;

}

Questa volta, rimuovendo il modulo col comando 'rmmod' si riesce ad interrompere il processo.

In definitiva abbiamo mostrato come i FIFO realtime possano essere usati per le comunicazioni inter-processo. Inoltre, l'esempio esposto aiuta a comprendere perché sia necessario ricorrere a RTLinux.


Avanti Indietro Indice