2010-02-08 15 views
8

Sto utilizzando un segnale in tempo reale in Linux per ricevere notifiche sull'arrivo di nuovi dati in una porta seriale. Sfortunatamente, ciò causa la sospensione delle chiamate a riposo quando c'è un segnale. Qualcuno sa di un modo per evitare questo comportamento.Come evitare l'interruzione delle chiamate a riposo a causa di un segnale in Linux

Modifica: Ho provato a utilizzare un segnale regolare (SIGUSR1) ma continuo a ottenere lo stesso comportamento.

Grazie, Joao

risposta

12

Dalla manpage nanosleep:

nanosleep ritarda l'esecuzione del programma per almeno il tempo specificato in req *. La funzione può tornare prima se un segnale è stato consegnato al processo. In questo caso, restituisce -1, imposta errno su EINTR e scrive il tempo rimanente nella struttura puntata da rem a meno che rem non sia NULL. Il valore di * rem può quindi essere utilizzato per richiamare nuovamente il nanosleep e completare la pausa specificata.

+0

Andrò con questo. Ho dato uno sguardo all'interno delle librerie POCO e la loro implementazione Thread :: sleep fa qualcosa come te descritto. Grazie – jassuncao

+0

Non dimenticare di controllare la risposta selezionata. –

+1

Non lo farò, ma preferisco aspettare un po 'prima di accettare una risposta. – jassuncao

2

Se non si vuole essere interrotto, perché stai usando il segnale in tempo reale?

Da qualche parte, nella "Advanced Unix Programming" di Rockind o nel libro di Steven, c'era un esempio di come fingere questo. Prendi nota dell'ora attuale prima di iniziare a dormire. Dopo che il sonno è terminato, si controlla per assicurarsi che sia trascorso il tempo richiesto e, in caso contrario, si inizia un nuovo sonno. Metti il ​​sonno in un ciclo che calcola il tempo di andare e dorme quella quantità, ed esce quando il tempo richiesto è passato.

+0

Ci sono tutti i tipi di problemi relativi a questo se l'orologio di sistema cambia. Ecco perché POSIX offre funzioni di orologio molto più sofisticate rispetto alla semplice chiamata "sleep", che dovrebbe essere completamente abbandonata ... –

7

È possibile mascherare quasi tutti i segnali (ad eccezione di SIGKILL) utilizzando le chiamate sigprocmask() o signal(). Il primo ti restituirà la maschera precedente, che puoi recuperare dopo lo sleep(). Alcuni esempi sono here. Se ciò non aiuta, per favore, sii più dettagliato di quale segnale interrompe il tuo sonno. Penso, puoi anche controllare questa condizione ("sonno interrotto dal segnale?") E cadere di nuovo nel sonno.

+0

Il tuo link di esempio è rotto. – OxyDeadbeef

+0

Avendo i nomi delle funzioni non è difficile trovare altri esempi, ad es. [Introduzione alla programmazione dei segnali Unix] (http://titania.ctie.monash.edu.au/signals/). –

2

Bene, un segnale in tempo reale dovrebbe interrompere il sonno. Potresti invece utilizzare un segnale non in tempo reale. Un altro approccio è quello di verificare se è trascorso il tempo di sonno previsto, e in caso contrario, dormire per l'intervallo rimanente.

+0

Grazie per la risposta, ma l'utilizzo di un segnale regolare interrompe anche le chiamate a riposo. – jassuncao

5

I nuovi kernel Linux supportano signalfd(2). Questo, insieme a sigprocmask(2), è un modo molto efficace per combinare la gestione del segnale e degli eventi I/O in una singola chiamata epoll_wait(2).

+0

Questo è un modo davvero brutto e non portabile per fare qualcosa che è fatto facilmente con la portabilità completa anche per i sistemi legacy (il trucco self-pipe) o per tutti i moderni sistemi conformi a POSIX (con 'pselect'). –

+3

La portabilità è un obiettivo onorevole, ma non sempre il primo. –

+0

L'unica ragione * per non * essere portatile in questa istanza è l'ottimizzazione prematura, che è la radice di tutto il male. C'è un enorme branco di pecore Linux che fanno proselitismo di 'epoll' per le prestazioni, mentre a meno che non si gestiscano centinaia di migliaia di descrittori di file alla volta, il semplice' sondaggio 'non sarà mai il collo di bottiglia (e anche allora quasi sicuramente non lo sarà). Non bere il koolaid. –

Problemi correlati