Quali sono le differenze tra sondaggio e selezione?


Risposte:


90

Penso che questo risponda alla tua domanda:

Da Richard Stevens (rstevens@noao.edu):

La differenza di base è che fd_set di select () è una maschera di bit e quindi ha una dimensione fissa. Sarebbe possibile che il kernel non limiti questa dimensione quando il kernel viene compilato, consentendo all'applicazione di definire FD_SETSIZE come vuole (come i commenti nell'intestazione del sistema implicano oggi) ma ci vuole più lavoro. 4.4 Il kernel diBSD e la funzione di libreria Solaris hanno entrambi questo limite. Ma vedo che BSD / OS 2.1 è stato ora codificato per evitare questo limite, quindi è fattibile, solo una piccola questione di programmazione. :-) Qualcuno dovrebbe presentare una segnalazione di bug di Solaris su questo, e vedere se è mai stato corretto.

Con poll (), tuttavia, l'utente deve allocare un array di strutture pollfd e passare il numero di voci in questo array, quindi non ci sono limiti fondamentali. Come osserva Casper, un numero inferiore di sistemi ha poll () rispetto a select, quindi quest'ultimo è più portatile. Inoltre, con le implementazioni originali (SVR3) non è stato possibile impostare il descrittore su -1 per dire al kernel di ignorare una voce nella struttura pollfd, che ha reso difficile rimuovere le voci dall'array; SVR4 aggira questo. Personalmente, utilizzo sempre select () e raramente poll (), perché porto anche il mio codice su ambienti BSD. Qualcuno potrebbe scrivere un'implementazione di poll () che utilizza select (), per questi ambienti, ma non ne ho mai visto uno. Sia select () che poll () vengono standardizzati da POSIX 1003.1g.

Aggiornamento di ottobre 2017:

L'e-mail citata sopra ha almeno il 2001; il poll()comando è ora (2017) supportato su tutti i sistemi operativi moderni, incluso BSD. In effetti, alcune persone credono che select() dovrebbe essere deprecato . Opinioni a parte, i problemi di portabilità in giro poll()non sono più una preoccupazione per i sistemi moderni. Inoltre, epoll()da allora è stato sviluppato (puoi leggere la pagina man ) e continua a crescere in popolarità.

Per lo sviluppo moderno probabilmente non vuoi usare select(), anche se non c'è nulla di esplicitamente sbagliato in esso. poll(), ed è l'evoluzione più moderna epoll(), fornisce le stesse caratteristiche (e altro) come select()senza soffrire dei limiti in essa contenuti.


15
Quando è stata scritta la risposta di Stevens? Il commento sul sondaggio () non disponibile su BSD si applica ancora? MacOS X (che è parzialmente basato su BSD) ha poll () e lo standard POSIX (POSIX 2008) lo richiede.
Jonathan Leffler

12
Rich Stevens è deceduto nel settembre 1999, quindi la risposta deve essere più antica di così. Cita di aver visto un nuovo cambiamento in BSD / OS 2.1, che è stato rilasciato nel gennaio 1996, quindi probabilmente in quel periodo.
alanc,

2
Non ci credo. Risposta inviata 5 anni fa, mi inciampo su di esso, lo lascio aperto nel browser. Il giorno successivo, l'autore modifica e migliora la risposta. SO mi avvisa con l'aggiornamento sulla pagina usando AJAX / websocket. ecco perché SO è fantastico
Steven Lu,

9
@StevenLu Sì, ma sfortunatamente nessuna parola sull'uso di AJAX / websocket selecto poll:(
Christopher Schultz,

> Qualcuno potrebbe scrivere un'implementazione di poll () che utilizza select (), per questi ambienti, ma non ne ho mai visto uno. Java lo fa ;-)
Sergey Mashkov il

229

La select()chiamata è di creare tre bitmasks a marchio che prese e descrittori di file che si desidera vedere per la lettura, la scrittura, e gli errori, e poi i marchi del sistema operativo quali infatti hanno avuto qualche tipo di attività; poll()hai creato un elenco di ID descrittori e il sistema operativo contrassegna ciascuno di essi con il tipo di evento che si è verificato.

Il select()metodo è piuttosto goffo e inefficiente.

  1. In genere ci sono più di mille potenziali descrittori di file disponibili per un processo. Se un processo di lunga durata ha solo pochi descrittori aperti, ma almeno uno di essi è stato assegnato un numero elevato, allora la maschera di bit passata select()deve essere abbastanza grande da accogliere quel descrittore più alto, quindi intere gamme di centinaia di bit saranno essere disinserito dal fatto che il sistema operativo deve eseguire il ciclo ad ogni select()chiamata solo per scoprire che non sono impostati.

  2. Una volta select()restituito, il chiamante deve scorrere su tutte e tre le maschere di bit per determinare quali eventi hanno avuto luogo. In molte applicazioni tipiche solo uno o due descrittori di file riceveranno nuovo traffico in qualsiasi momento, tuttavia tutte e tre le maschere di bit devono essere lette fino alla fine per scoprire quali descrittori sono.

  3. Poiché il sistema operativo ti segnala l'attività riscrivendo le maschere di bit, sono rovinate e non sono più contrassegnate con l'elenco di descrittori di file che desideri ascoltare. O devi ricostruire l'intera maschera di bit da qualche altra lista che tieni in memoria, oppure devi conservare una copia duplicata di ciascuna maschera di bit e memcpy()il blocco di dati sopra le maschere di bit rovinate dopo ogni select()chiamata.

Così la poll() approccio funziona molto meglio perché puoi continuare a riutilizzare la stessa struttura di dati.

In effetti, poll()ha ispirato un altro meccanismo nei moderni kernel Linux:epoll() che migliora ancora di più il meccanismo per consentire un ulteriore salto di scalabilità, poiché i server di oggi vogliono spesso gestire decine di migliaia di connessioni contemporaneamente. Questa è una buona introduzione allo sforzo:

http://scotdoyle.com/python-epoll-howto.html

Mentre questo link ha alcuni bei grafici che mostrano i vantaggi di epoll()(noterai che select()a questo punto è considerato così inefficiente e vecchio stile che non ha nemmeno una linea su questi grafici!):

http://lse.sourceforge.net/epoll/index.html


Aggiornamento: ecco un'altra domanda Stack Overflow, la cui risposta fornisce ancora più dettagli sulle differenze:

Avvertenze sui reattori select / poll vs. epoll in Twisted


1
E +1 per il collegamento a un esempio di utilizzo di epoll in Python - sembra che ci siano alcuni esempi interessanti lì, e dovrò provarli ...
Allen George,

+1 per spiegare la risposta; -1 per menzionare epoll ma non kqueue
persona

Questa risposta fa sembrare che epoll sia sempre preferibile
user3467349

0

Entrambi sono lenti e per lo più uguali , ma di dimensioni diverse e alcune caratteristiche!

Quando scrivi un iteratore, devi copiare il set di selectogni volta! Mentre pollha risolto questo tipo di problema per avere un bellissimo codice. Un'altra differenza è che pollpuò gestire più di 1024 descrittori di file (FD) per impostazione predefinita. pollpuò gestire eventi diversi per rendere il programma più leggibile invece di avere molte variabili per gestire questo tipo di lavoro. Le operazioni in polle selectsono lineari e lente a causa di numerosi controlli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.