Jawaban:
Saya pikir ini menjawab pertanyaan Anda:
Dari Richard Stevens (rstevens@noao.edu):
Perbedaan mendasar adalah bahwa fd_set pilih () adalah topeng bit dan karenanya memiliki beberapa ukuran tetap. Adalah mungkin bagi kernel untuk tidak membatasi ukuran ini ketika kernel dikompilasi, memungkinkan aplikasi untuk mendefinisikan FD_SETSIZE untuk apa pun yang diinginkannya (seperti komentar di header sistem menyiratkan hari ini) tetapi membutuhkan lebih banyak pekerjaan. Kernel 4.4BSD dan fungsi pustaka Solaris keduanya memiliki batas ini. Tapi saya melihat bahwa BSD / OS 2.1 sekarang telah dikodekan untuk menghindari batas ini, jadi itu bisa dilakukan, hanya masalah pemrograman kecil. :-) Seseorang harus mengajukan laporan bug Solaris tentang ini, dan melihat apakah itu pernah diperbaiki.
Namun, dengan polling (), pengguna harus mengalokasikan array struktur pollfd, dan meneruskan jumlah entri dalam array ini, jadi tidak ada batasan mendasar. Seperti yang dicatat Casper, lebih sedikit sistem memiliki polling () daripada pilih, sehingga yang terakhir lebih portabel. Juga, dengan implementasi asli (SVR3) Anda tidak dapat mengatur deskriptor ke -1 untuk memberitahu kernel untuk mengabaikan entri dalam struktur pollfd, yang membuatnya sulit untuk menghapus entri dari array; SVR4 menyiasati ini. Secara pribadi, saya selalu menggunakan select () dan jarang poll (), karena saya porting kode saya ke lingkungan BSD juga. Seseorang dapat menulis implementasi polling () yang menggunakan select (), untuk lingkungan ini, tetapi saya belum pernah melihatnya. Baik select () dan poll () sedang distandarisasi oleh POSIX 1003.1g.
Email yang dirujuk di atas setidaknya setua tahun 2001; yang poll()
perintah sekarang (2017) didukung di semua sistem operasi modern - termasuk BSD. Bahkan, beberapa orang percaya bahwa itu select()
harus ditinggalkan . Selain pendapat, masalah portabilitas di sekitar poll()
tidak lagi menjadi perhatian pada sistem modern. Selanjutnya, epoll()
telah dikembangkan (Anda dapat membaca halaman manual ), dan terus meningkat popularitasnya.
Untuk pengembangan modern Anda mungkin tidak ingin menggunakannya select()
, meskipun tidak ada yang secara eksplisit salah dengannya. poll()
, dan ini adalah evolusi yang lebih modern epoll()
, memberikan fitur yang sama (dan lebih banyak) select()
tanpa menderita keterbatasan di dalamnya.
select
atau poll
:(
The select()
panggilan telah Anda buat tiga bitmasks untuk tanda yang soket dan deskriptor file yang ingin menonton untuk membaca, menulis, dan kesalahan, dan kemudian tanda sistem operasi mana yang sebenarnya memiliki beberapa jenis aktivitas; poll()
memiliki Anda membuat daftar ID descriptor, dan sistem operasi menandai masing-masing dengan jenis peristiwa yang terjadi.
The select()
Metode agak kikuk dan tidak efisien.
Biasanya ada lebih dari seribu deskriptor file potensial yang tersedia untuk suatu proses. Jika proses jangka panjang hanya memiliki beberapa deskriptor terbuka, tetapi setidaknya satu dari mereka telah diberi nomor tinggi, maka bitmask yang diteruskan select()
harus cukup besar untuk mengakomodasi deskriptor tertinggi - sehingga seluruh rentang ratusan bit akan tidak disetel bahwa sistem operasi harus mengulang setiap select()
panggilan hanya untuk mengetahui bahwa mereka tidak disetel.
Setelah select()
kembali, penelepon harus mengulangi ketiga bitmask untuk menentukan peristiwa apa yang terjadi. Dalam banyak aplikasi tipikal, hanya satu atau dua deskriptor file yang akan mendapatkan lalu lintas baru pada saat tertentu, namun ketiga bitmask harus dibaca sampai akhir untuk menemukan deskriptor mana.
Karena sistem operasi memberi sinyal kepada Anda tentang aktivitas dengan menulis ulang bitmasks, mereka hancur dan tidak lagi ditandai dengan daftar deskriptor file yang ingin Anda dengarkan. Anda juga harus membangun kembali seluruh bitmask dari daftar lain yang Anda simpan di memori, atau Anda harus menyimpan salinan duplikat dari setiap bitmask dan memcpy()
blok data di atas bitmask yang rusak setelah setiap select()
panggilan.
Jadi poll()
pendekatannya bekerja jauh lebih baik karena Anda dapat terus menggunakan kembali struktur data yang sama.
Faktanya, poll()
telah mengilhami mekanisme lain di kernel Linux modern: epoll()
yang semakin meningkatkan mekanisme untuk memungkinkan lompatan skalabilitas, karena server saat ini sering ingin menangani puluhan ribu koneksi sekaligus. Ini adalah pengantar yang bagus untuk upaya ini:
http://scotdoyle.com/python-epoll-howto.html
Meskipun tautan ini memiliki beberapa grafik bagus yang menunjukkan manfaat epoll()
(Anda akan perhatikan bahwa select()
pada titik ini dianggap sangat tidak efisien dan kuno sehingga bahkan tidak mendapatkan garis pada grafik ini!):
http://lse.sourceforge.net/epoll/index.html
Pembaruan: Berikut adalah pertanyaan Stack Overflow lainnya, yang jawabannya bahkan lebih detail tentang perbedaan:
Peringatan pemilihan / jajak pendapat vs reaktor epoll di Twisted
Keduanya lambat dan sebagian besar sama , tetapi berbeda dalam ukuran dan beberapa fitur!
Saat Anda menulis iterator, Anda harus menyalin set select
setiap waktu! Sementara poll
telah memperbaiki masalah semacam ini untuk memiliki kode yang indah. Perbedaan lainnya adalah bahwa poll
dapat menangani lebih dari 1024 file deskriptor (FD) secara default. poll
dapat menangani berbagai peristiwa untuk membuat program lebih mudah dibaca daripada memiliki banyak variabel untuk menangani pekerjaan semacam ini. Operasi dalam poll
dan select
linier dan lambat karena banyak cek.