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);
    }
}
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top