Jaki jest cel pierwszego argumentu, aby wybrać wywołanie systemowe?

25

Z man select

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

nfds to deskryptor pliku o najwyższym numerze w dowolnym z trzech zestawów plus 1.

Jaki jest cel nfds, kiedy już mamy readfds, writefdsi na exceptfdspodstawie którego można określić deskryptory plików?

phunehehe
źródło
Chciałem zapytać o SO, ale tutaj jest bardziej scentralizowany, a wywołania C API są rozważane na temat .
phunehehe

Odpowiedzi:

25

W „Advanced Programming in the UNIX Environment” W. Richard Stevens mówi, że jest to optymalizacja wydajności:

Określając najwyższy interesujący nas deskryptor, jądro może uniknąć przejścia setek nieużywanych bitów w trzech zestawach deskryptorów, szukając włączonych bitów.

(1. wydanie, strona 399)

Jeśli wykonujesz programowanie w systemach UNIX, książka APUE jest wysoce zalecana.


AKTUALIZACJA

fd_setZazwyczaj jest w stanie śledzić do 1024 deskryptorów.

Najbardziej efektywnym sposobem śledzenia, które fdssą ustawione 0i które są ustawione, 1byłby zestaw bitów, więc każdy fd_setskładałby się z 1024 bitów.

W systemie 32-bitowym długie int (lub „słowo”) ma 32 bity, co oznacza, że ​​każde fd_setma
1024/32 = 32 słowa.

Jeśli nfdsjest coś małego, takiego jak 8 lub 16, co byłoby w wielu aplikacjach, wystarczy zajrzeć do pierwszego słowa, które powinno być wyraźnie szybsze niż zajrzenie do wszystkich 32.

(Zobacz FD_SETSIZEi __NFDBITSod /usr/include/sys/select.hwartości na twojej platformie.)


AKTUALIZACJA 2

Co do tego, dlaczego podpis funkcji nie jest

int select(fd_set *readfds, int nreadfds,
           fd_set *writefds, int nwritefds,
           fd_set *exceptfds, int nexceptfds,
           struct timeval *timeout);

Sądzę, że to dlatego, że kod próbuje zachować wszystkie argumenty w rejestrach , więc procesor może na nich pracować szybciej, a jeśli musiałby śledzić dodatkowe 2 zmienne, procesor może nie mieć wystarczającej liczby rejestrów.

Innymi słowy, selectujawnia szczegół implementacji, aby mógł być szybszy.

Mikel
źródło
2
To lub nowszy The Linux Programming Interface
Chris
APUE również został niedawno zaktualizowany. Drugie wydanie: amazon.com/gp/aw/d.html/ref=aw_d_detail?pd=1&a=0201433079
Mikel
@chris Sprawdzę interfejs programowania Linux. Dzięki.
Mikel
Dzięki za informacje, sprawdzę książki, kiedy będę miał trochę czasu.
phunehehe
APUE 2nd Ed: 27 czerwca 2005 (obejmuje Linux-2.4.22) TLPI: październik 2010 (obejmuje Linux-2.6.35)
Chris
6

Nie wiem na pewno, ponieważ nie jestem jednym z projektantów select (), ale powiedziałbym, że to optymalizacja wydajności. Funkcja wywołująca wie, ile deskryptorów plików umieściła w plikach odczytu, zapisu i oprócz FD, więc dlaczego jądro powinno to rozgryzać?

Pamiętaj, że na początku lat 80., kiedy wprowadzono select (), nie mieli wielu gigagherców i procesorów do pracy. VAX 25 MHz był dość szybki. Ponadto chciałeś, aby select () działał szybko, gdyby mógł: jeśli niektóre operacje wejścia / wyjścia czekały na proces, po co zmuszać proces do oczekiwania?

Bruce Ediger
źródło
Do twojego argumentu powiedziałbym, że potrzebujemy nreadfds, nwritefdsa nexceptfdsnie tylko jednego nfds.
phunehehe
Może jest tak, że nfdsmożna przejść do rejestru, aby uzyskać szybszy dostęp. Gdyby musiał śledzić trzy liczby wraz ze wszystkimi innymi argumentami, być może procesor nie miałby wystarczającej liczby rejestrów. Oczywiście jądro mogło stworzyć własne nfdsna podstawie 3 hipotetycznych zmiennych. Domyślam się, że ujawnia szczegół implementacji w celu zwiększenia wydajności.
Mikel
@Mikel, phunehehe: Oddzielne nfdsargumenty przyniosłyby bardzo niewielki zysk. W większości przypadków proces otworzył bardzo niewiele procesów w stosunku do FD_SETSIZE. Typowy przypadek może mieć (4,4,2) z 1024; sprawdzenie jądra (4,4,4) to duża wygrana (1024,1024,1024), ale optymalizacja do (4,4,2) byłaby prawie bezużyteczna.
Gilles „SO- przestań być zły”
@Gilles: zysk byłby czystszym API. (W tej chwili albo programista musi wykonać dodatkową pracę, aby obliczyć nfds, albo być leniwym i zadzwonić select(FD_SETSIZE, ...), co byłoby wolniejsze.)
Mikel
OTOH, śledzenie tylko jednej maksymalnej zmiennej może być łatwiejsze dla programisty.
Mikel