select (Unix) - select (Unix)

редактировать

select- это системный вызов и интерфейс прикладного программирования (API) в Unix-подобных и POSIX -совместимых операционных системах для проверки состояния файловых дескрипторов открытого ввода / выходные каналы. Системный вызов select аналогичен функции poll , представленной в UNIX System V и более поздних операционных системах. Однако с проблемой c10k и select, и poll были заменены подобными kqueue, epoll и портами завершения ввода / вывода.

Одним из распространенных способов использования select вне заявленного использования ожидания дескрипторов файлов является реализация переносимого субсекундного сна. Это может быть достигнуто путем передачи NULL для всех трех аргументов fd_set и длительности желаемого сна в качестве аргумента тайм-аута.

В языке программирования C системный вызов select объявлен в заголовочном файле sys / select.h или unistd.h и имеет следующий синтаксис:

int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout);
аргументописание
nfdsЭто целое число, на единицу больше максимального для любого дескриптора файла в любом из наборов. Другими словами, добавляя дескрипторы файлов к каждому из наборов, вы должны вычислить максимальное целочисленное значение для всех из них, затем увеличить это значение на единицу и затем передать это как nfds.
readfdsfd_setТип, содержащий дескрипторы файлов, которые нужно проверить на предмет готовности к чтению, а на выходе указывает, какие дескрипторы файлов готовы к чтению. Может иметь тип NULL.
writefdsfd_set, содержащий дескрипторы файлов, которые нужно проверить на готовность к записи, а на выходе указывает, какие дескрипторы файлов готовы к записи. Может иметь значение NULL.
errorfdsfd_set, в котором хранятся дескрипторы файлов, которые должны быть проверены на наличие ожидающих условий ошибки, а на выходе указывает, какие файловые дескрипторы имеют ожидающие условия ошибки. Может быть NULL.
timeoutструктура типа struct timeval, которая указывает максимальный интервал ожидания завершения выбора. Если аргумент тайм-аута указывает на объект типа struct timeval, члены которого равны 0, select ()не блокируется. Если аргумент тайм-аута - ПУСТО (NULL), select () блокируется до тех пор, пока событие не приведет к возврату одной из масок с допустимым (ненулевым) значением. Linux обновит тайм-аут на месте, чтобы указать, сколько времени прошло, хотя это поведение не характерно для большинства других систем Unix.

fd_set typeаргументами можно управлять с помощью четырех служебных макросов: FD_SET (), FD_CLR (), FD_ZERO ()и FD_ISSET ().

Select возвращает общее число битов, установленных в readfds, writefdsи errorfds, или ноль, если время ожидания истекло, и -1 в случае ошибки.

Наборы файловых дескрипторов, используемых в select, имеют конечный размер в зависимости от операционной системы. Новый системный вызов pollобеспечивает более гибкое решение.

Содержание
  • 1 Пример
  • 2 См. Также
  • 3 Ссылки
  • 4 Внешние ссылки
Пример
#include #include #include #include #include #include #include #include #include #include #include #include #define PORT "9421" / * прототипы функций * / void die (const char *); int main (int argc, char ** argv) {int sockfd, new, maxfd, on = 1, nready, я; struct addrinfo * res0, * res, hints; буфер символов [BUFSIZ]; fd_set master, readfds; int error; ssize_t nbytes; (void) memset (hints, '\ 0', sizeof (struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; if (0! = (error = getaddrinfo (NULL, PORT, hints, res0))) errx (EXIT_FAILURE, "% s", gai_strerror (error)); for (res = res0; res; res = res->ai_next) {if (-1 == (sockfd = socket (res->ai_family, res->ai_socktype, res->ai_protocol))) {perror ("socket () "); Продолжать; } если (-1 == (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) on, sizeof (int)))) {perror ("setsockopt ()"); Продолжать; } если (-1 == (привязка (sockfd, res->ai_addr, res->ai_addrlen))) {perror ("bind ()"); Продолжать; } перемена; } если (-1 == sockfd) выход (EXIT_FAILURE); freeaddrinfo (res0); если (-1 == (слушать (sockfd, 32))) умереть ("слушать ()"); если (-1 == (fcntl (sockfd, F_SETFD, O_NONBLOCK))) die ("fcntl ()"); FD_ZERO (мастер); FD_ZERO (readfds); FD_SET (sockfd, мастер); maxfd = sockfd; while (1) {memcpy (readfds, master, sizeof (master)); (void) printf ("выполняется выбор () \ n"); если (-1 == (nready = select (maxfd + 1, readfds, NULL, NULL, NULL))) die ("select ()"); (void) printf ("Количество готовых дескрипторов:% d \ n", nready); для (я = 0; я <=maxfd nready>0; я ++) {если (FD_ISSET (я, readfds)) {nready--; if (i == sockfd) {(void) printf ("Попытка принять () новое соединение (я) \ n"); если (-1 == (новое = принять (sockfd, NULL, NULL))) {если (EWOULDBLOCK! = errno) die ("accept ()"); перемена; } else {if (-1 == (fcntl (новый, F_SETFD, O_NONBLOCK))) die ("fcntl ()"); FD_SET (новый, главный); if (maxfd < new) maxfd = new; } } else { (void)printf("recv() data from one of descriptors(s)\n"); nbytes = recv(i, buffer, sizeof(buffer), 0); if (nbytes <= 0) { if (EWOULDBLOCK != errno) die("recv()"); break; } buffer[nbytes] = '\0'; printf("%s", buffer); (void)printf("%zi bytes received.\n", nbytes); close(i); FD_CLR(i, master); } } } } return 0; } void die(const char *msg) { perror(msg); exit(EXIT_FAILURE); }
См. также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-07 09:15:31
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте