Tempo rimanente su una chiamata select ()
Domanda
Sto usando select()
su una piattaforma Linux / ARM per vedere se un socket udp ha ricevuto un pacchetto. Vorrei sapere quanto tempo rimaneva nella chiamata selezionata se ritorna prima del timeout (dopo aver rilevato un pacchetto).
Qualcosa sulla falsariga di:
int wait_fd(int fd, int msec)
{
struct timeval tv;
fd_set rws;
tv.tv_sec = msec / 1000ul;
tv.tv_usec = (msec % 1000ul) * 1000ul;
FD_ZERO( & rws);
FD_SET(fd, & rws);
(void)select(fd + 1, & rws, NULL, NULL, & tv);
if (FD_ISSET(fd, &rws)) { /* There is data */
msec = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
return(msec?msec:1);
} else { /* There is no data */
return(0);
}
}
Soluzione
La cosa più sicura è ignorare l'ambigua definizione di select()
e cronometrarla da soli.
Prendi il tempo prima e dopo la selezione e sottralo dall'intervallo desiderato.
Altri suggerimenti
Se ricordo correttamente, la funzione select () tratta il timeout e un parametro I / O e quando select restituisce il tempo rimanente viene restituito nella variabile timeout.
Altrimenti, dovrai registrare l'ora corrente prima di chiamare, e di nuovo dopo e ottenere la differenza tra i due.
Da " man seleziona " su OSX:
Timeout is not changed by select(), and may be reused on subsequent calls, however it
is good style to re-ini-tialize it before each invocation of select().
Devi chiamare gettimeofday prima di chiamare select, quindi gettimeofday all'uscita.
[Modifica] Sembra che Linux sia leggermente diverso:
(ii) The select function may update the timeout parameter to indicate
how much time was left. The pselect function does not change
this parameter.
On Linux, the function select modifies timeout to reflect the amount of
time not slept; most other implementations do not do this. This causes
problems both when Linux code which reads timeout is ported to other
operating systems, and when code is ported to Linux that reuses a
struct timeval for multiple selects in a loop without reinitializing
it. Consider timeout to be undefined after select returns.
Linux select () aggiorna l'argomento timeout per riflettere il tempo trascorso.
Nota che questo non è portatile su altri sistemi (quindi l'avvertimento nel manuale di OS X citato sopra) ma funziona con Linux.
Gilad
Non usare select, prova con fd maggiore di 1024 con il tuo codice e vedi cosa otterrai.