Quais são as diferenças entre pesquisa e seleção?

163

Refiro-me às chamadas da API C do sistema de seleção e pesquisa padrão do POSIX .

Steven Lu
fonte

Respostas:

90

Eu acho que isso responde à sua pergunta:

De Richard Stevens ([email protected]):

A diferença básica é que o fd_set de select () é uma máscara de bit e, portanto, possui um tamanho fixo. Seria possível para o kernel não limitar esse tamanho quando o kernel é compilado, permitindo que o aplicativo defina FD_SETSIZE para o que ele quiser (como os comentários no cabeçalho do sistema implicam hoje), mas é preciso mais trabalho. O kernel do 4.4BSD e a função de biblioteca Solaris têm esse limite. Mas vejo que o BSD / OS 2.1 agora foi codificado para evitar esse limite, portanto é factível, apenas uma pequena questão de programação. :-) Alguém deve registrar um relatório de bug do Solaris sobre isso e ver se ele é corrigido.

Com poll (), no entanto, o usuário deve alocar uma matriz de estruturas pollfd e passar o número de entradas nessa matriz, para que não haja limite fundamental. Como observa Casper, menos sistemas têm poll () do que select, então o último é mais portátil. Além disso, com as implementações originais (SVR3), você não pode definir o descritor como -1 para dizer ao kernel para ignorar uma entrada na estrutura pollfd, o que dificultava a remoção de entradas da matriz; O SVR4 contorna isso. Pessoalmente, eu sempre uso select () e raramente poll (), porque também porto meu código para ambientes BSD. Alguém poderia escrever uma implementação de poll () que usa select (), para esses ambientes, mas eu nunca vi uma. Ambos select () e poll () estão sendo padronizados pelo POSIX 1003.1g.

Atualização de outubro de 2017:

O email mencionado acima é pelo menos tão antigo quanto 2001; poll()agora, o comando (2017) é suportado em todos os sistemas operacionais modernos - incluindo BSD. De fato, algumas pessoas acreditam que isso select() deve ser preterido . Opiniões à parte, as questões de portabilidade poll()não são mais uma preocupação nos sistemas modernos. Além disso, epoll()já foi desenvolvido (você pode ler a página do manual ) e continua a aumentar em popularidade.

Para o desenvolvimento moderno, você provavelmente não deseja usar select(), embora não haja nada explicitamente errado. poll(), e é uma evolução mais moderna epoll(), fornece os mesmos recursos (e mais) que select()sem sofrer com as limitações nele contidas.

akappa
fonte
15
Quando foi escrita a resposta de Stevens? O comentário sobre poll () não estar disponível no BSD ainda se aplica? O MacOS X (que é parcialmente baseado no BSD) possui poll (), e o padrão POSIX (POSIX 2008) exige isso.
Jonathan Leffler
12
Rich Stevens faleceu em setembro de 1999, então a resposta tem que ser mais antiga que isso. Ele menciona ter visto uma nova alteração no BSD / OS 2.1, lançada em janeiro de 1996, provavelmente por volta de então.
Alanc
2
Eu não acredito nisso. Resposta postada 5 anos atrás, eu me deparo com ela, deixo aberta no navegador. No dia seguinte, o autor edita e aprimora a resposta. SO notifica-me com a atualização na página usando AJAX / websocket. É por isso que é ótimo
Steven Lu
9
@StevenLu Sim, mas infelizmente nenhuma palavra sobre se o AJAX / websocket está usando selectou poll:(
Christopher Schultz
Alguém poderia escrever uma implementação de poll () que usa select () para esses ambientes, mas eu nunca vi uma. Java faz isso ;-)
Sergey Mashkov
229

Na select()chamada, você cria três máscaras de bits para marcar quais soquetes e descritores de arquivo você deseja observar quanto a leitura, gravação e erros e, em seguida, o sistema operacional marca quais de fato tiveram algum tipo de atividade; poll()você criou uma lista de IDs do descritor e o sistema operacional marca cada um deles com o tipo de evento que ocorreu.

O select()método é bastante desajeitado e ineficiente.

  1. Normalmente, existem mais de mil descritores de arquivo em potencial disponíveis para um processo. Se um processo de longa execução tiver apenas alguns descritores abertos, mas pelo menos um deles tiver sido atribuído a um número alto, a máscara select()de bit transmitida deverá ser grande o suficiente para acomodar o descritor mais alto - de modo que intervalos inteiros de centenas de bits serão esteja desabilitado para que o sistema operacional tenha que percorrer todas as select()chamadas apenas para descobrir que está desabilitado.

  2. Uma vez select()retornado, o chamador precisa fazer um loop nas três máscaras de bits para determinar quais eventos ocorreram. Em muitas aplicações típicas, apenas um ou dois descritores de arquivo receberão novo tráfego a qualquer momento, mas as três máscaras de bits devem ser lidas até o fim para descobrir quais são esses descritores.

  3. Como o sistema operacional sinaliza sobre a atividade reescrevendo as máscaras de bits, elas são arruinadas e não são mais marcadas com a lista de descritores de arquivos que você deseja ouvir. Você precisa recriar a máscara de bits inteira a partir de outra lista que mantém na memória ou manter uma cópia duplicada de cada máscara de máscara e memcpy()o bloco de dados sobre as máscaras arruinadas após cada select()chamada.

Portanto, a poll()abordagem funciona muito melhor porque você pode continuar reutilizando a mesma estrutura de dados.

De fato, poll()inspirou mais um mecanismo nos kernels modernos do Linux: o epoll()que aprimora ainda mais o mecanismo para permitir mais um salto na escalabilidade, pois os servidores de hoje geralmente desejam lidar com dezenas de milhares de conexões ao mesmo tempo. Esta é uma boa introdução ao esforço:

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

Embora este link tenha alguns gráficos interessantes mostrando os benefícios de epoll()(você notará que select(), neste ponto, é considerado tão ineficiente e antiquado que nem sequer obtém uma linha nesses gráficos!):

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


Atualização: Aqui está outra pergunta do Stack Overflow, cuja resposta fornece ainda mais detalhes sobre as diferenças:

Advertências de reatores select / poll vs. epoll em Twisted

Brandon Rhodes
fonte
1
E um para ligar para um exemplo do uso epoll em python - parece que há alguns exemplos interessantes lá, e eu vou ter de testá-los ...
Allen George
+1 para explicar a resposta; -1 para mencionar epoll mas não kqueue
Boa Pessoa
Esta resposta faz com que pareça que o epoll é sempre preferível
#
0

Ambos são lentos e quase todos iguais , mas diferentes em tamanho e algum tipo de recurso!

Ao escrever um iterador, você precisa copiar o conjunto de selecttodas as vezes! Enquanto pollcorrigiu esse tipo de problema para ter um código bonito. Outra diferença é que pollpode lidar com mais de 1024 descritores de arquivo (FDs) por padrão. pollpode manipular eventos diferentes para tornar o programa mais legível, em vez de ter muitas variáveis ​​para lidar com esse tipo de trabalho. As operações no polle selectsão lineares e lentas por causa de muitas verificações.

Amir Fo
fonte