First, review the previous Select
Select Advantages:
currently supported on almost all platforms, and its good cross-platform support is one of its advantages
Select Cons:
1. Each call to select () requires that the FD collection be copied from the user state to the kernel state, which is very expensive when FD is very large, and each call to select () requires the kernel to traverse all the FD that is passed in, which is also very expensive in FD.
2. There is a maximum limit on the number of file descriptors that a single process can monitor, typically 1024 on Linux, which can be improved by modifying the macro definition or even recompiling the kernel, but this also results in reduced efficiency
Ii. Overview of poll functions
Like the essence of the Select () and poll () system calls, the mechanism of poll () is similar to select (), with no significant difference in nature with select (), and the management of multiple descriptors is also polling, which is handled according to the state of the descriptor, but poll () There is no limit to the maximum number of file descriptors (but performance is also degraded if the number is too large). The disadvantage of poll () and select () is that an array containing a large number of file descriptors is copied in between the user state and the kernel's address space, regardless of whether the file descriptor is ready, and its overhead increases linearly as the number of file descriptors increases. The poll () function describes the header file:
[CSharp]View Plain Copy
- #include <poll.h>
function Body:
[CSharp]View Plain Copy
- int poll (struct POLLFD *fds, nfds_t nfds, int timeout);
Features:
Monitor and wait for property changes for multiple file descriptors
Parameters:
FDS: A pointer to the NO. 0 element of a struct array, each of which is a struct POLLFD structure that specifies the condition for testing a given FD
[CSHARP] view plain copy
- STRUCT&NBSP;POLLFD{&NBSP;&NBSP;
- int fd; //file descriptor
- short events; //waiting event
- short revents; //the events actually occurred
- };&NBSP;&NBSP;
FD: Each pollfd struct specifies a monitored file descriptor that can pass multiple structures, indicating that poll () monitors multiple file descriptors.
Events: Specifies the event (input, output, error) that monitors FD, with multiple values for each event, as follows:
The Revents:revents field is the action result event for the file descriptor, and the kernel sets the field when the call returns. Any events requested in the events domain may be returned in the revents domain.
Note: The events field of each struct is set by the user, telling the kernel what we are interested in, and the revents domain is the kernel set at the time of the return to indicate what happened to the descriptor.
Nfds: Used to specify the number of elements in the first parameter array
Timeout: Specifies the number of milliseconds to wait for poll () to return, regardless of whether I/O is ready.
return value:
On success, poll () returns the number of file descriptors that are not 0 in the Revents field in the struct, or poll () returns 0 if no events occur before the timeout;
On Failure, poll () returns 1 and sets errno to one of the following values:
EBADF: Invalid file descriptor specified in one or more structs.
The address that the Efault:fds pointer points to exceeds the address space of the process.
EINTR: The requested event generates a signal before the call can be re-initiated.
The Einval:nfds parameter exceeds the Plimit_nofile value.
Enomem: There is not enough memory available to complete the request.
Iii. Examples of poll example
Implement UDP to send and receive code with poll:
[CSharp]View Plain Copy
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <poll.h>
- int main (int argc,char *argv[])
- {
- int udpfd = 0;
- int ret = 0;
- struct POLLFD fds[2]; //Monitor file Description structure array: 2 x
- struct sockaddr_in saddr;
- struct sockaddr_in caddr;
- Bzero (&saddr,sizeof (SADDR));
- saddr.sin_family = af_inet;
- Saddr.sin_port = htons (8000);
- SADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);
- Bzero (&caddr,sizeof (CADDR));
- caddr.sin_family = af_inet;
- Caddr.sin_port = htons (8000);
- //Create sockets
- if ((UDPFD = socket (af_inet,sock_dgram, 0)) < 0)
- {
- Perror ("socket error");
- Exit (-1);
- }
- //Socket Port binding
- if (Bind (UDPFD, (struct sockaddr*) &saddr, sizeof (SADDR))! = 0)
- {
- Perror ("bind error");
- Close (UDPFD);
- Exit (-1);
- }
- printf ("input: \" Sayto 192.168.220.x\ "to Sendmsg to somebody\033[32m\n");
- FDS[0].FD = 0; //Standard input descriptor
- FDS[1].FD = UDPFD; //UDP Descriptor
- Fds[0].events = Pollin; //Normal or priority with data- readable
- Fds[1].events = Pollin; //Normal or priority with data- readable
- While (1)
- {
- //monitor and wait for multiple files (standard input, UDP socket) Descriptor property changes (readable)
- //No attribute changes, this function blocks until a change is performed, no timeout is set here
- RET = Poll (FDS, 2,-1);
- Write (1,"UDPQQ:", 6);
- if (ret = =-1) { //error
- Perror ("poll ()");
- }
- Else if (Ret > 0) { //prepared file descriptor
- char buf[100] = {0};
- if ((fds[0].revents & pollin) = = Pollin) { //Standard input
- Fgets (buf, sizeof (BUF), stdin);
- Buf[strlen (BUF)-1] = ' + ';
- if (strncmp (buf, "Sayto", 5) = = 0)
- {
- char ipbuf[16] = "";
- Inet_pton (Af_inet, buf+6, &caddr.sin_addr); //Assign a value to the addr socket address.
- printf ("\rsay to%s\n", Inet_ntop (Af_inet,&caddr.sin_addr,ipbuf,sizeof (IPBUF)));
- continue;
- }
- Else if (strcmp (buf, "exit") ==0)
- {
- Close (UDPFD);
- Exit (0);
- }
- SendTo (UDPFD, buf, strlen (BUF), 0, (struct sockaddr*) &caddr, sizeof (CADDR));
- }
- Else if ((fds[1].revents & pollin) = = Pollin) { //udp socket
- struct sockaddr_in addr;
- char Ipbuf[inet_addrstrlen] = "";
- socklen_t Addrlen = sizeof (addr);
- Bzero (&addr,sizeof (addr));
- Recvfrom (UDPFD, buf, 0, (struct sockaddr*) &addr, &addrlen);
- printf ("\r\033[31m[%s]:\033[32m%s\n", Inet_ntop (Af_inet,&addr.sin_addr,ipbuf,sizeof (IPBUF)), buf);
- }
- }
- Else if (0 = = ret) { //timeout
- printf ("Time out\n");
- }
- }
- return 0;
- }
Operation Result:
Poll function of--I/O multiplexing for Linux network programming