답변:
나는 생각 이 귀하의 질문에 대한 대답 :
Richard Stevens (rstevens@noao.edu)에서 :
기본적인 차이점은 select ()의 fd_set이 비트 마스크이므로 고정 크기가 있다는 것입니다. 커널이 컴파일 될 때 커널이이 크기를 제한하지 않을 수 있으므로 응용 프로그램이 FD_SETSIZE를 원하는대로 정의 할 수 있지만 (시스템 헤더의 주석이 오늘날 암시하는 것처럼) 더 많은 작업이 필요합니다. 4.4BSD의 커널과 Solaris 라이브러리 기능에는이 제한이 있습니다. 그러나 BSD / OS 2.1은 이제이 한계를 피하기 위해 코딩되었으므로 작은 프로그래밍 문제만으로도 가능합니다. :-) 누군가 이것에 대한 Solaris 버그 보고서를 제출하고 수정되었는지 확인해야합니다.
그러나 poll ()을 사용하면 사용자는 pollfd 구조의 배열을 할당하고이 배열의 항목 수를 전달해야하므로 기본 제한이 없습니다. 캐스퍼가 지적한 바와 같이, 선택보다 poll ()이 적은 시스템이 적기 때문에 후자가 더 이식성이 뛰어납니다. 또한 원래 구현 (SVR3)에서는 커널이 pollfd 구조의 항목을 무시하도록 지시하기 위해 디스크립터를 -1로 설정할 수 없어서 배열에서 항목을 제거하기가 어려웠습니다. SVR4가이 문제를 해결했습니다. 개인적으로 필자는 항상 코드를 BSD 환경으로 이식하기 때문에 항상 select () 및 거의 poll ()을 사용하지 않습니다. 누군가가 이러한 환경에서 select ()를 사용하는 poll ()의 구현을 작성할 수는 있지만 본 적이 없습니다. select () 및 poll () 모두 POSIX 1003.1g에 의해 표준화되고 있습니다.
위에서 언급 한 이메일은 2001 년 이전의 것입니다. 이 poll()
명령은 BSD를 포함한 모든 최신 운영 체제에서 지원됩니다 (2017). 실제로 일부 사람들은 select()
더 이상 사용되지 않아야 한다고 생각합니다 . 의견과는 별도로, 이식성 문제 poll()
는 더 이상 현대 시스템에서 문제가되지 않습니다. 또한 epoll()
그 이후로 개발되었으며 ( man 페이지를 읽을 수 있음 ) 계속 인기가 높아지고 있습니다.
현대 개발 select()
의 경우 명시 적으로 아무 것도 없지만 을 사용하고 싶지 않을 것입니다. poll()
보다 현대적인 진화 epoll()
이며, select()
그로 인한 제한없이 동일한 기능을 제공합니다 .
select
또는 poll
:(
이 select()
호출에서는 읽기, 쓰기 및 오류에 대해보고자하는 소켓 및 파일 설명자를 표시하기 위해 3 개의 비트 마스크를 작성하고 운영 체제는 실제로 어떤 종류의 활동이 있었는지 표시합니다. poll()
디스크립터 ID 목록을 작성했으며 운영 체제는 각각 의 이벤트 종류 를 표시합니다 .
이 select()
방법은 다소 복잡하고 비효율적입니다.
일반적으로 프로세스에 사용 가능한 잠재적 인 파일 설명자가 천 개가 넘습니다. 장기 실행 프로세스에 설명자가 몇 개만 열려 있지만 그 중 하나 이상에 높은 수의 할당이 지정된 경우 전달 된 비트 마스크는 select()
가장 높은 설명자를 수용 할 수있을 정도로 커야합니다. 따라서 전체 수백 비트 범위 운영 체제가 설정되지 않았 음 select()
을 발견하기 위해 모든 호출 에서 루프를 반복 하도록 설정하지 마십시오.
일단 select()
반환 되면 호출자는 3 개의 비트 마스크를 모두 반복하여 어떤 이벤트가 발생했는지 확인해야합니다. 매우 많은 일반적인 응용 프로그램에서는 주어진 순간에 하나 또는 두 개의 파일 디스크립터 만 새 트래픽을 가져 오지만 3 개의 비트 마스크를 모두 끝까지 읽어서 어떤 디스크립터인지 확인해야합니다.
운영 체제는 비트 마스크를 다시 작성하여 활동에 대한 신호를 보내기 때문에 파멸되어 더 이상 듣고 자하는 파일 디스크립터 목록으로 표시되지 않습니다. 메모리에 보관하고있는 다른 목록에서 전체 비트 마스크를 다시 작성하거나 memcpy()
각 select()
호출 후에 파쇄 된 비트 마스크 위에 각 비트 마스크와 데이터 블록의 복제본을 보관해야합니다 .
따라서 poll()
동일한 데이터 구조를 계속 재사용 할 수 있으므로 접근 방식이 훨씬 더 효과적입니다.
사실, poll()
현대 리눅스 커널의 또 다른 메커니즘에 영감을주었습니다. epoll()
오늘날 서버는 종종 한 번에 수만 개의 연결을 처리하기를 원하기 때문에 확장 성이 한층 더 향상 될 수있는 메커니즘을 더욱 향상시킵니다. 이것은 노력에 대한 좋은 소개입니다.
http://scotdoyle.com/python-epoll-howto.html
이 링크에는 장점을 보여주는 멋진 그래프가 있지만 epoll()
( select()
이 시점까지는 비효율적이고 구식으로 간주되어 이러한 그래프에 선이 표시되지 않습니다!)
http://lse.sourceforge.net/epoll/index.html
업데이트 : 여기에 또 다른 스택 오버플로 질문이 있습니다.