Newsgroup: it.comp.os.linux.development
Titolo: Comunicazione seriale e multithread

Non sono un esperto di comunicazione RS232 sotto Linux, né tantomeno di 
programmazione multithreading. Quindi vi faccio un domandone, sperando non sia 
banale.
Devo scrivere un'applicazione che gira sotto linux e che deve comunicare, via 
RS232, con una apparecchiatura. Il protocollo di comunicazione è il tipico 
domanda e risposta: l'applicazione sotto linux invia un comando e aspetta la 
risposta. Il ciclo si ripete all'infinito.
Ovviamente tra l'invio della domanda e la ricezione della risposta può passare 
un po' di tempo oppure la risposta potrebbe anche non essere mai ricevuta 
(l'apparecchiatura è spenta o non funzionante).
Secondo voi qual è il modo migliore per gestire questo tipo di problema?
Stavo pensando di creare un thread a parte che gestisce la comunicazione e che 
può anche bloccarsi sulla ricezione per un certo timeout. All'arrivo della 
risposta, questo thread riempie una struttura dati globale che il thread 
principale si preoccupa di memorizzare su filesystem.
E' un approccio valido, oppure sto cercando di uccidere la mosca con un cannone?
Nel caso di creazione di due thread, che tipo di comunicazione posso metter su 
tra i due thread?

 posso metter su tra i due thread?
Se vuoi usare i thread, la soluzione migliore è usare delle queue.
Saluti  Manlio Perillo

 Secondo voi qual è il modo migliore per gestire questo tipo di problema?
Io gestisco la comunicazione attraverso una porta UART (seriale) tra due 
dispositivi.
Dovevo fare proprio la tua stessa cosa e ho risolto in questo modo:
invio un messaggio da un dispositivo e subito mi metto in ascolto. La fase 
di ascolto è soggetta ad un timeout in modo che l'ascolto non sia totalmente 
bloccante.
Se ricevo il messaggio di risposta o se scade il timeout posso quindi 
inviare un nuovo messaggio.
Spero di esserti stato utile
ciao

 Spero di esserti stato utile
E' più o meno quello che faccio già se programmo un semplice microcontrollore 
con UART. Ricevo i dati mediante interrupt su UART e li memorizzo in RAM. Ogni 
tanto richiamo la routine che gestisce i pacchetti ricevuti da seriale e se ce 
n'è uno ricevuto o è passato un timeout, rimando un nuovo pacchetto.
Mi sembrava un metodo abbastanza semplice che poteva andare su dispositivi senza 
sistema operativo. Mi chiedevo se ci fosse un meccanismo più elegante per fare 
una cosa del genere sotto linux.
Per esempio, una situazione simile si ha con la rete. Se il client deve 
comunicare con un server invia dei pacchetti TCP e aspetta la risposta, 
naturalmente gestendo un timeout.
Chi programma con i socket, come fa ad aspettare i pacchetti da ricevere senza 
bloccare il tutto (immaginiamo ci sia anche una GUI, come in un browser Web)?
Gestisce un altro thread per la comunicazione, imposta una callback all'arrivo 
del pacchetto o cos'altro?

 sincronizzazione.
Beh, sì... sono disposto a complicarmi la vita se è un approccio valido.
Il mio problema sembra essere molto simile, così come dicevo nell'altra mia 
risposta, all'applicazione di un client. Per esempio, un browser web ha una 
interfaccia grafica da gestire e la comunicazione tramite la rete TCP/IP.
Anche lì bisogna inviare dati ed aspettare le risposte entro un certo timeout.
Come si risolve lì il problema?

 browser Web)?
Puoi usare la select().
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

 Ma le UART sono gestite tramite linux?
beh si! io programmo su questo
http://www.xbow.com/Products/productsdetails.aspx?sid=85
questo dispositivo ha dentro linux (con kernel 2.4....)
Ha una porta  UART che serve a comunicare con un altro dispositivo

 certo timeout. Come si risolve lì il problema?
Non conosco i dettagli, ma di certo la maggioranza usa i thread.
Se la libreria GUI è thread safe, possono aggiornare l'interfaccia 
grafica direttamente dal thread "di lavoro" (ma poche GUI sono thread 
safe in questo modo, una delle poche eccezioni è forse Windows, dato che 
la sua API di sistema si basa pesantemente su threads)
Con le PyQT, ad esempio, puoi mandare un segnale tra thread diversi. 
Sotto il cofano questo è implementato usando una queue.
Per non bloccare il thread principale dell'applicazione nell'attesa che 
la queue abbia dei dati disponibili, quello che fanno è un polling della 
queue ad ogni iterazione del ciclo principale dell'applicazione.
Saluti  Manlio Perillo

 Puoi usare la select().
Ma la select() è normalmente bloccante, giusto? Scegli se vuoi aspettare che un 
file descriptor sia pronto per la lettura, per la scrittura oppure abbia un 
errore. Nel frattempo, però, il tuo programma è bloccato, almeno fino ad un 
certo timeout. Se il timeout è di 1 minuto, non posso tenere bloccato il task 
per tutto questo tempo.
Potrei usare un timeout più basso, diciamo 100ms, ed eventualmente richiamare la 
select 10 volte per avere 1 secondo totale di timeout. Ma mi sembra anche questo 
approccio un po' complicato e poco elegante.
Io pensavo ad un thread che usa la select() bloccante anche per 1 minuto intero, 
tanto c'è il thread principale che gira in continuazione. Dite che sbaglio?
Non c'è un esempio di applicazione client (tipo un semplice ftp client o 
qualcosa di simile) dove posso vedere la tecnica di programmazione?

 qualcosa di simile) dove posso vedere la tecnica di programmazione?
Un cliente ftp (da linea di comando) non è multi-thread.  Il cliente 
telnet in genere lo è ma usa la fork() per creare un nuovo processo. 
Uno gestisce la tastiera e invia in rete i comandi e l'altro riceve 
dalla rete e gestisce i comandi.


 rete e gestisce i comandi.
--------------------^^^^^^^
Ops .. intendevo le risposte dei comandi.


 
Scusa, devo fare un terminale in python. Avevo proprio il dubbio sul
discorso invio e ricezione:
e' ammesso che il programma principale si occupi della trasmissione e il
thread della ricezione? Ovvero se se il thread legge mentre il programma
principale scrive (sullo stesso file descriptor naturalmente) succedono
casini?
Grazie, Nicola.
-- 
chi va pian va san e va lontan

 casini?
Non ho esperienza di programmazione coi thread ma credo che non faccia 
alcuna differenza con quanto avviene con la fork().


 rete e gestisce i comandi.
Solitamente telnet e' single thread e usa select() sia per leggere la 
tastiera che per leggere dalla rete, e' possibile mettere sulla select 
anche il file descriptor dell'stdin.
Bye,
  Gabry

 casini?
Ti infili in una serie di casini senza fine, anche perche' se fai fork() 
come dice Giovanni ti ritrovi con due programmi diversi che possono 
comunicare solo con pipe, shared memory o schifezze simili.
Input e output in un terminale sono altamente accoppiate, quindi e' 
buona norma tenerle nello stesso processo, e se possibile, anche nello 
stesso thread.
Per quanto riguarda l'input, puoi anche decidere se riceverlo in line 
mode o character mode (cioe' se la select ti scatta ogni volta che 
digiti un carattere o quando premi return), se vuoi facilitarti le cose 
poi librerie come readline o simili ti astraggono le problematiche di 
interazione a basso livello con il terminale e ti danno anche la 
possibilita' di gestione di history, navigazione della stringa col 
cursore, ecc, ecc.
Bye,
  Gabry

 
premetto che non ho letto bene la conversazione, però lascia stare i thread se 
possibile! Esistono select() e la scrittura/lettura non-bloccante. Con quelle 
due cose lì generalmente non hai bisogno di altro.
-- 
SF
Well, the second little piggy
Well, he was kinda stokin', spent most of his days just a ganja smokin'
Hoppin' and a-boppin' down on Venice Beach
Gettin' paid money for religious speech
Built his shelter from what he garbage picked
Mostly made up of old cans and sticks
Then one day he was crankin' out Bob Marley
Along came the wolf on his big, bad Harley

 
Non tutte le implementazioni usano la select().


 digiti un carattere o quando premi return),
Purtroppo devo leggere un carattere alla volta.


 alcuna differenza con quanto avviene con la fork().
Boh, qualcuno sembra un po' scettico sulla questione.
Sto' propendendo per un unico thread.


 altro.
Alla select ci sono arrivato da molto tempo, sopratutto dopo aver visto un
thread che faceva il polling continuo e si mangiava il 99% della cpu :O
E' il thread + select il mio problema.


 
elimina una sorgente di problemi: il thread. ;-)
-- 
SF
Alle primarie del PD vota Rosy Bindi, perchè bellezza e intelligenza possono 
andare di pari passo!