Newsgroup: it.comp.os.linux.development
Titolo: Condividere una porta seriale tra due processi e tecnica IPC da usare

Ho un dispositivo collegato alla porta seriale di una linux box che
comunica
con un protocollo proprietario a domanda e risposta (la domanda è
sempre
iniziata dal PC).
Due processi indipendenti e che non possono essere riunificati possono
accedere,
in tempi casuali (dipendenti dalle operazioni dell'utente) al
dispositivo collegato alla
porta seriale.
Ho quindi la necessità di regolamentare l'accesso alla porta seriale
per evitare
sovrapposizioni di comandi.
Avevo pensato di procedere in questo modo, magari qualcuno mi può
confermare
l'efficacia.
Creo un processo che è l'unico a colloquiare fisicamente con la
seriale. Tutte le
richieste di accesso alla seriale avvengono tramite questo processo. I
due processi
principali che vogliono comunicare con il dispositivo, comunicano in
realtà con
il processo che gestisce la seriale mediante una named pipe.
In pratica il processo della seriale aprirà due named pipes e leggerà
le richieste
da queste. Quando vede una richiesta pronta in una delle pipes la
inoltra alla
porta seriale, aspetta l'eventuale risposta e la reinoltra sulla
stessa pipe.
Che ne dite? E' fattibile?
Un'altra possibilità era quella di far gestire ai due processi
principali l'accesso alla
seriale. La regolamentazione per evitare la sovrapposizione di accessi
avviene in
automatico perchè, se è attiva una comunicazione con il processo1, il
processo2
troverà la porta seriale occupata e non potrà aprirla, quindi sarà
costretto ad aspettare.
Ma facendo così devo riscrivere le routine di accesso alla seriale su
entrambi i processi,
a meno di non creare una piccola libreria condivisa tra i due.

 costretto ad aspettare.
bah, se l'accesso alla seriale dei processi è frequente, rischi che uno
dei due non vi acceda quasi mai

ah, ho quotato come i cani

 dei due non vi acceda quasi mai
No, in realtà l'accesso alla seriale non è frequente e ci sono
sicuramente
dei buchi che impediscono che un processo blocchi definitivamente la
seriale.
Stavo ragionando su questa strada che mi sembra più facile da
implementare,
però mi sono subito imbattutto in un problema. Due processi
indipendenti
possono aprire senza problemi il file /dev/ttyS0 in lettura/scrittura.
Io mi
aspettavo che la open() ritornasse un errore se si tentava di aprire
una seconda
volta una stessa seriale.
Forse devo lavorare con i File Locks?

 Forse devo lavorare con i File Locks?
anche

 anche
Penso che proseguirò per ora con la strada dei 2 processi
che richiamano loro stessi delle funzioni di libreria tx/rx su
seriale.
La libreria si occupa di aprire la seriale e bloccarla, così l'altro
processo non potrà utilizzare la seriale nello stesso momento
fin quando la prima transazione non sarà finita.
In questo modo evito di usare l'IPC tra i processi che mi sembra
più complicato.

 a meno di non creare una piccola libreria condivisa tra i due.
Perchè non provi con un approccio asincrono?In problemi di questo tipo ti 
semplifica parecchio. Ci sono librerie per un po' tutti i linguaggi (C++, 
Python, Perl, etc.)
Ciao
-- 
"Le opinioni dei fanatici prescindono dai fatti"
python -c "print 'bG9ybWF5bmFAZ21haWwuY29t'.decode('base64')"

 fin quando la prima transazione non sarà finita.
Non so se è la strada giusta...
proc1 apre la seriale e la blocca ed effettua la sua transazione
che può durare diciamo un secondo. proc1 può essere richiamato
dall'utente un certo numero di volte, per esempio 10 volte in un
secondo.
La stessa cosa succede per proc2.
Supponiamo di richiamare per prima proc1 che apre la seriale e
la blocca. Se proc2 viene richiamato prima che proc1 termini,
ovviamente fallisce la fnclt() per bloccare a sua volta la seriale,
quindi capisce che deve aspettare perchè c'è un altro processo
che la sta usando.
Il problema è: come implementare questa attesa fin quando la
seriale viene sbloccata da proc1?
Se proc2 fa 5 tentativi di bloccare la seriale a distanza di 1
secondo
prima di dichiarare un problema, potrebbe rischiare di beccare le
successive altre chiamate di proc1 e quindi di vedere la seriale
sempre
bloccata, quando in realtà si sblocca ogni tanto.
Sarebbe bello poter avere una specie di prelazione. proc2 vede la
seriale bloccata ed attiva una prelazione. Se proc1 dovesse essere
richiamato, vedrebbe la prelazione di proc2 e aspetterebbe lui stesso
che questa prelazione scompaia.
Che dite? E' fattibile in qualche modo semplice? Devo utilizzare
semafori?
Forse basta anche un semplice file che segna la prelazione di uno dei
processi nei confronti dell'altro concorrente.
Oppure mi sto incasinando e basta?

 Python, Perl, etc.)
Il programma sarà in C.
Se non ho capito male, l'approccio asincrono permette di avere delle
chiamate di I/O (read() e write() in primis) non bloccanti. Ma non so
se può
risolvere il problema della sovrapposizione dei comandi su seriale.
Se proc1 scrive su seriale e torna subito aspettando la risposta,
proc2 a sua volta
potrebbe scrivere su seriale prima di ricevere la risposta al primo
comando.

 Oppure mi sto incasinando e basta?
pthread_cond_wait non va' bene?
-- 
SF
Facciamo quello per cui siamo stati addestrati, per cui siamo stati cresciuti, 
per cui siamo nati. Niente prigionieri, nessuna pietà. Inizio memorabile.



Non è proprio così, c'è un solo processo (spesso chiamato reactor) che si 
occupa di gestire le chiamate bloccanti.
Potresti fare in modo che il controllo del programma ti ritorni solo 
quando il proc1 ha non solo finito di scrivere, ma ha anche ricevuto 
indietro la risposta, non dovrebbe essere difficile una volta capito bene 
il meccanismo delle callback.


 pthread_cond_wait non va' bene?
Però sembra che vada bene per più thread di uno stesso processo.
Nel mio caso io ho due distinti processi...

 il meccanismo delle callback.
Certo, questo è quello che effettivamente farò. Però il problema è che proc2 
potrebbe tentare di scrivere sulla seriale quando proc1 è ancora in esecuzione. 
Il fatto che proc1 termini ed esca solo dopo una completa transazione sulla 
seriale, non impedisce a proc2 di utilizzare la seriale... d'altronde linux è 
multitasking.
Non capisco come la modalità asincrona di lettura/scrittura possa aiutarmi nel 
regolare il traffico sulla seriale.

 seriale viene sbloccata da proc1?
Ho scoperto che la richiesta di mettere un lock ad un file mediante la fcntl() 
può essere fatta in due modi: se il lock non si può mettere (il file è già 
bloccato da qualche altro processo) la fcntl() ritorna subito con un errore. 
Oppure è possibile richiedere il lock in modo bloccante: la fcntl() non torna 
fin quando il lock non può essere piazzato.
Così risolvo in modo semplice, anche se ho paura che, per un qualche errore 
(proc1 che blocca perennemente la seriale) proc2 possa bloccarsi sulla fcntl() 
per sempre.

 
No, questo è uno dei grossi malintesi quando si inizia a lavorare con un 
framework asincrono. Le chiamate sono sempre bloccanti, ma il meccanismo 
a callback permette di ridurre al minimo la sezione di codice bloccante e 
quindi di rendere il tutto parallelizzabile


 quindi di rendere il tutto parallelizzabile
A questo punto, per evitarti la scrittura di un trattato, ti chiedo di darmi 
qualche risorsa per capire meglio il tuo punto di vista.

pozz wrote:

e perchè non fai un'applicazione MT? :-)


> meccanismo a callback permette di ridurre al minimo la
Io ho usato twisted, il framework asincrono per python, è fatto 
abbastanza bene (anche se ha dei limiti). Magari puoi leggerti un po' di 
coumentazione per capire come funziona e poi utilizzare la libreria 
specifica per c. Questo è il link del tutorial: 
http://twistedmatrix.com/
projects/core/documentation/howto/book.pdf
Ciao
P.S.
Scrivi pure anche in privato se hai bisogno
