Domanda

while (xxx) {
    timeout.tv_sec=TIMEOUT;
    timeout.tv_usec=0;
    FD_ZERO(&set); 
    FD_SET(sd,&set);

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout))
    xxxxx
}

funziona bene, tuttavia

FD_ZERO(&set); 
FD_SET(sd,&set);

while (xxx) {
    timeout.tv_sec=TIMEOUT;
    timeout.tv_usec=0;

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout))
    xxxxx
}

non lo fa. Funziona la prima volta, ma alla successiva esecuzione del ciclo while ottiene un timeout anche se il socket SD riceve i dati. Mi sembra uno spreco di risorse dover svuotare e riempire il set ogni volta.

Qualcuno ha una buona spiegazione del perché questo, e ancora meglio, forse un suggerimento su come evitarlo?

È stato utile?

Soluzione

select modifica i suoi argomenti. Devi davvero reinizializzarlo ogni volta.

Se sei preoccupato per l'overhead, il costo di elaborazione dell'intero FD_SET nel kernel è leggermente più significativo del costo di FD_ZERO. Vorresti solo passare il tuo massimo fd, non FD_SETSZIZE, per minimizzare l'elaborazione del kernel. Nel tuo esempio:

switch (select((sd + 1),&set,NULL,NULL,&timeout))

Per un caso più complesso con più fds, in genere si finisce per mantenere una variabile massima:

FD_SET(sd,&set);
if (sd > max) max = sd;
... repeat many times...

switch (select((max + 1),&set,NULL,NULL,&timeout))


Se avrai un gran numero di descrittori di file e sei preoccupato per il sovraccarico di schlepping, dovresti guardare alcune delle alternative per selezionare (). Non menzioni il sistema operativo che stai utilizzando, ma per i sistemi operativi simili a Unix ce ne sono alcuni:

  • per Linux, epoll ()
  • per FreeBSD / NetBSD / OpenBSD / MacOS X, kqueue ()
  • per Solaris, / dev / poll

Le API sono diverse, ma sono essenzialmente un'interfaccia kernel con stato per mantenere una serie di descrizioni di file attive. Una volta aggiunto un fd al set, riceverai una notifica degli eventi su quel fd senza doverlo ripetere continuamente.

Altri suggerimenti

Leggi la pagina man select. Il set restituito è solo i descrittori di file che sono pronti per essere utilizzati. Dovresti usare FD_ISSET per controllare ognuno se è impostato o meno.

Inizializza sempre fd_set prima di usarlo.

Ecco come funziona select. Funziona meglio e ha più senso se hai più di un socket. Questo è un po 'il punto: stai selezionando tra più socket. Se vuoi leggere da un socket, basta leggerlo o recuperarlo.

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