Направлять ввод/вывод на различные файловые дескрипторы
#include <sys/poll.h>int poll( struct pollfd *fds,nfds_t nfds,int timeout );
libc
Функция poll() предоставляет приложениям механизм мультиплексирования операций ввода/вывода над набором файловых дескрипторов.
Аргумент fds - это массив из структур struct pollfd.
Функция poll() проверяет каждый член массива файловых дескрипторов fds на предмет наличия событий, указанных в events. Количество структур struct pollfd в массиве fds определяется аргументом nfds. Членами массива являются структуры struct pollfd, внутри которых fd указывает на дескриптор открытого файла, а аргументы events и revents представляют собой битовые маски, построенные с помощью комбинации (операция ИЛИ) следующих флагов событий:
POLLOUT
являются взаимоисключающими; устройство не является доступным для записи, если до этого произошло его отключение. Однако это событие совместимо с POLLIN
, POLLRDNORM
, POLLRDBAND
или POLLPRI
. Если удаленный сокет закрыт, poll() возвращает событие POLLIN
, а не POLLHUP
. Этот флаг действителен только в битовой маске revents и игнорируется в events. POLLRDNORM
| POLLRDBAND
. POLLOUT
. Значение и семантика обычных, приоритетных и высокоприоритетных данных зависят от файла и устройства.
Если значение fd меньше, чем 0
, события events игнорируются, а для revents устанавливается значение 0
в этой записи при возврате из poll().
В каждой структуре struct pollfd poll() очищает элемент revents, за исключением тех случаев, когда приложение запрашивало отчет об условии, задав один из битов events, перечисленных выше, функция poll() устанавливает соответствующий бит в revents, если запрошенное условие истинно. Кроме того, функция poll() устанавливает флаг POLLHUP
, POLLERR
и POLLNVAL
в revents, если условие истинно, даже если приложение не установило соответствующий бит в events.
Если ни одно из определенных событий не происходит ни в одном из выбранных файловых дескрипторов, функция poll() выдерживает timeout миллисекунд, чтобы событие произошло в любом из них. Если значение timeout равно 0
, poll() возвращается немедленно. Если значение timeout равно -1
, poll() блокируется до тех пор, пока не произойдет запрошенное событие или пока вызов не будет прерван.
Флаг O_NONBLOCK
не влияет на функцию poll().
Функция poll() позволяет опрашивать обычные файлы, терминальные и псевдотерминальные устройства, FIFO и каналы.
Обычные файлы обычно имеют статус TRUE на чтение и запись.
Дескриптор файла для сокета, который прослушивает соединения, указывает, что он готов к чтению, как только соединения станут доступны. Дескриптор файла для сокета, который подключается асинхронно, указывает, что он готов к записи после того, как соединение было установлено.
#include <sys/socket.h>#include <netinet/in.h>#include <sys/poll.h>#include <arpa/inet.h>#include <unistd.h>#include <stdio.h>#include <pthread.h>#include <fcntl.h>#include <errno.h>#include <string.h>struct sockaddr_in sad;void * client( void *arg ){int s;const char *p = "Some data\n";if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ){perror( "socket" );return (NULL);}if ( connect( s, (struct sockaddr *)&sad, sizeof( sad ) ) == -1 ){perror("connect");return (NULL);}write( s, p, strlen( p ) );close( s );return (NULL);}int main( void ){struct pollfd fds;int s = -1, s2 = -1, done_accept = 0, oflags, ret;char buf[100];if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ){perror( "socket" );return (1);}sad.sin_family = AF_INET;sad.sin_len = sizeof( sad );sad.sin_addr.s_addr = inet_addr( "127.0.0.1" );sad.sin_port = htons( 1234 );fds.fd = s;fds.events = POLLRDNORM;oflags = fcntl( s, F_GETFL );oflags |= O_NONBLOCK;fcntl( s, F_SETFL, oflags );if ( bind( s, (struct sockaddr *)&sad, sizeof( sad ) ) == -1 ){perror( "bind" );return (1);}listen( s, 5 );if ( (ret = pthread_create( NULL, NULL, client, NULL )) != EOK ){fprintf( stderr, "pthread_create: %s\n", strerror( ret ) );return (1);}for ( ; ; ){if ( (ret = poll( &fds, 1, -1 )) == -1 ){perror( "poll" );break;} elseif ( ret != 1 || (fds.revents & POLLRDNORM) == 0 ){break;}if ( done_accept ){if ( (ret = read( s2, buf, sizeof( buf ) )) <= 0 ){break;}printf( "%s", buf );} else {if ( (s2 = accept( s, NULL, 0 )) == -1 ){perror( "accept" );break;}fds.fd = s2;done_accept = 1;}}close( s );close( s2 );return (0);}
POSIX 1003.1 X/Open Systems Interfaces Extension
Не все менеджеры поддерживают POLLPRI
, POLLPRI
, POLLERR
и POLLHUP
.
struct pollfd, read(), select(), write()
Предыдущий раздел: Описание API системной библиотеки