Sự khác biệt giữa cuộc thăm dò và lựa chọn là gì?


Câu trả lời:


90

Tôi nghĩ rằng điều này trả lời câu hỏi của bạn:

Từ Richard Stevens (rstevens@noao.edu):

Sự khác biệt cơ bản là fd_set của select () là mặt nạ bit và do đó có một số kích thước cố định. Hạt nhân có thể không giới hạn kích thước này khi kernel được biên dịch, cho phép ứng dụng xác định FD_SETSIZE theo bất cứ điều gì nó muốn (như các bình luận trong tiêu đề hệ thống ngụ ý ngày nay) nhưng phải mất nhiều công sức hơn. Nhân của 4.4BSD và chức năng thư viện Solaris đều có giới hạn này. Nhưng tôi thấy rằng BSD / OS 2.1 hiện đã được mã hóa để tránh giới hạn này, vì vậy điều đó là có thể, chỉ là một vấn đề nhỏ về lập trình. :-) Ai đó nên nộp báo cáo lỗi Solaris về điều này và xem nó có được sửa hay không.

Tuy nhiên, với poll (), người dùng phải phân bổ một mảng các cấu trúc pollfd và vượt qua số lượng mục trong mảng này, do đó không có giới hạn cơ bản. Như Casper lưu ý, ít hệ thống có poll () hơn select, do đó, hệ thống này dễ mang theo hơn. Ngoài ra, với các triển khai ban đầu (SVR3), bạn không thể đặt bộ mô tả thành -1 để báo cho kernel bỏ qua một mục trong cấu trúc pollfd, điều này khiến cho việc loại bỏ các mục khỏi mảng trở nên khó khăn; SVR4 có được điều này. Cá nhân, tôi luôn sử dụng select () và hiếm khi thăm dò ý kiến ​​(), vì tôi cũng chuyển mã của mình sang môi trường BSD. Ai đó có thể viết một triển khai thăm dò ý kiến ​​() sử dụng select () cho các môi trường này, nhưng tôi chưa bao giờ thấy một môi trường nào. Cả select () và poll () đang được chuẩn hóa bởi POSIX 1003.1g.

Cập nhật tháng 10 năm 2017:

Các email được tham chiếu ở trên ít nhất là năm 2001; các poll()bao gồm BSD - lệnh bây giờ (2017) được hỗ trợ trên tất cả các hệ điều hành hiện đại. Trong thực tế, một số người tin rằng select() nên được phản đối . Các ý kiến ​​sang một bên, các vấn đề di động xung quanh poll()không còn là mối quan tâm trên các hệ thống hiện đại. Hơn nữa, epoll()kể từ đó đã được phát triển (bạn có thể đọc trang man ) và tiếp tục tăng phổ biến.

Đối với sự phát triển hiện đại, có lẽ bạn không muốn sử dụng select(), mặc dù không có gì sai rõ ràng với nó. poll()và đó là sự tiến hóa hiện đại hơn epoll(), cung cấp các tính năng tương tự (và hơn thế nữa) select()mà không phải chịu những hạn chế trong đó.


15
Khi nào câu trả lời của Stevens được viết? Nhận xét về cuộc thăm dò ý kiến ​​() không có sẵn trên BSD có còn được áp dụng không? MacOS X (một phần dựa trên BSD) có poll () và tiêu chuẩn POSIX (POSIX 2008) yêu cầu nó.
Jonathan Leffler

12
Rich Stevens đã qua đời vào tháng 9 năm 1999, vì vậy câu trả lời phải cũ hơn thế. Ông đề cập đến việc nhìn thấy một sự thay đổi mới trong BSD / OS 2.1, được phát hành vào tháng 1 năm 1996, vì vậy có lẽ vào khoảng thời gian đó.
alanc

2
Tôi không tin điều đó. Câu trả lời được đăng 5 năm trước, tôi vấp phải nó, để nó mở trong trình duyệt. Ngay ngày hôm sau, tác giả chỉnh sửa và cải thiện câu trả lời. SO thông báo cho tôi với cập nhật trên trang bằng AJAX / websocket. đây là lý do tại sao SO là tuyệt vời
Steven Lu

9
@StevenLu Có, nhưng tiếc là không có thông tin nào về việc AJAX / websocket đang sử dụng selecthay poll:(
Christopher Schultz

> Ai đó có thể viết một triển khai thăm dò ý kiến ​​() sử dụng select () cho các môi trường này, nhưng tôi chưa bao giờ thấy một môi trường nào. Java làm như vậy ;-)
Sergey Mashkov

229

Cuộc select()gọi yêu cầu bạn tạo ba bitmas để đánh dấu ổ cắm và mô tả tệp nào bạn muốn xem để đọc, viết và lỗi và sau đó hệ điều hành đánh dấu những hoạt động nào trong thực tế đã có một loại hoạt động nào đó; poll()bạn có tạo một danh sách ID mô tả và hệ điều hành đánh dấu mỗi ID đó với loại sự kiện đã xảy ra.

Các select()phương pháp là khá vụng về và kém hiệu quả.

  1. Thông thường có hơn một nghìn mô tả tệp tiềm năng có sẵn cho một quy trình. Nếu một quy trình chạy dài chỉ có một vài mô tả được mở, nhưng ít nhất một trong số chúng đã được gán một số lượng lớn, thì bitmask được truyền vào select()phải đủ lớn để chứa bộ mô tả cao nhất đó - vì vậy toàn bộ phạm vi hàng trăm bit sẽ không được đặt trước rằng hệ điều hành phải lặp đi lặp lại trên mỗi select()cuộc gọi chỉ để phát hiện ra rằng chúng không được đặt.

  2. Sau khi select()trả về, người gọi phải lặp qua cả ba bitmas để xác định sự kiện nào đã diễn ra. Trong rất nhiều ứng dụng điển hình, chỉ có một hoặc hai mô tả tệp sẽ có lưu lượng truy cập mới tại bất kỳ thời điểm nào, nhưng cả ba bitmas phải được đọc từ đầu đến cuối để khám phá những mô tả đó là gì.

  3. Bởi vì hệ điều hành báo hiệu cho bạn về hoạt động bằng cách viết lại bitmasks, chúng bị hủy hoại và không còn được đánh dấu bằng danh sách mô tả tệp bạn muốn nghe. Bạn có thể phải xây dựng lại toàn bộ bitmask từ một số danh sách khác mà bạn giữ trong bộ nhớ hoặc bạn phải giữ một bản sao của mỗi bitmask và memcpy()khối dữ liệu trên đầu các bitmas bị hủy hoại sau mỗi select()cuộc gọi.

Vì vậy, poll()cách tiếp cận hoạt động tốt hơn nhiều vì bạn có thể tiếp tục sử dụng lại cấu trúc dữ liệu tương tự.

Trên thực tế, poll()đã truyền cảm hứng cho một cơ chế khác trong các nhân Linux hiện đại: epoll()cải thiện hơn nữa cơ chế này để cho phép một bước nhảy vọt khác về khả năng mở rộng, vì các máy chủ ngày nay thường muốn xử lý hàng chục ngàn kết nối cùng một lúc. Đây là một giới thiệu tốt cho nỗ lực:

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

Mặc dù liên kết này có một số biểu đồ đẹp cho thấy lợi ích của epoll()(bạn sẽ lưu ý rằng select()đến thời điểm này được coi là không hiệu quả và lỗi thời đến nỗi nó thậm chí không có được một dòng trên các biểu đồ này!):

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


Cập nhật: Đây là một câu hỏi khác về Stack Overflow, câu trả lời của nó thậm chí còn chi tiết hơn về sự khác biệt:

Hãy cẩn thận với các lò phản ứng chọn / thăm dò so với epoll trong Twisted


1
Và +1 để liên kết với một ví dụ về sử dụng epoll trong python - có vẻ như có một số ví dụ thú vị ở đó, và tôi sẽ phải thử chúng ...
Allen George

+1 để giải thích câu trả lời; -1 để đề cập đến epoll nhưng không phải kqueue
Người tốt

Câu trả lời này làm cho nó có vẻ như epoll luôn luôn thích hợp hơn
user3467349

0

Cả hai đều chậm và chủ yếu giống nhau , nhưng khác nhau về kích thước và một số loại tính năng!

Khi bạn viết một trình vòng lặp, Bạn cần sao chép bộ selectmỗi lần! Trong khi pollđã sửa loại vấn đề này để có mã đẹp. Một sự khác biệt khác là pollcó thể xử lý hơn 1024 mô tả tệp (FD) theo mặc định. pollcó thể xử lý các sự kiện khác nhau để làm cho chương trình dễ đọc hơn thay vì có nhiều biến để xử lý loại công việc này. Hoạt động trong pollselectlà tuyến tính và chậm vì có nhiều kiểm tra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.