"Go" Linux system I/O Multiplexing Technology II: Poll ()--good

Source: Internet
Author: User
Tags goto int size readable

Original URL: http://www.cnblogs.com/alyssaCui/archive/2013/04/01/2993886.html

Poll

Poll or select is familiar to most unix/linux programmers, and these two things are similar in principle, there is no significant difference in performance, but Select has a limited number of file descriptors to monitor, so here's a poll to explain.

1. Header files

# include < Sys/poll. H>

2. Parameter description

int poll (struct POLLFD * FDS, unsigned int nfds, int timeout);

Unlike select (), poll () does not use the inefficient three bit-based file descriptor set, but instead employs a separate struct POLLFD array, which is pointed to by the FDS pointer. The POLLFD structure is defined as follows:

struct POLLFD

{

int FD; /* File Descriptor */

Short events; /* Events Waiting for */

Short revents; /* Events that have actually occurred */

} ;

typedef unsigned long nfds_t;

struct POLLFD * FDS : is an array of struct POLLFD struct types that holds the socket descriptor for which the state needs to be detected, and the system does not need to empty the array after calling this function, which is convenient to operate, especially if the socket is more connected. To a certain extent, it can improve the efficiency of processing; unlike the Select () function, the Select () function needs to empty the set of socket descriptors it detects by calling the Select () function, causing each call to select () The socket descriptor must be re-added to the set to be detected before, so the Select () function is suitable for cases where only a small number of socket descriptors are detected, whereas the poll () function is suitable for a large number of socket descriptors;

If the socket descriptor to be detected is negative, the detection of this descriptor is ignored, that is, the member variables events are not detected, events registered on the event will be ignored, the poll () function returns, the member variable revents is set to 0, Indicates that no event occurred;

Event tokens that are frequently detected:

Pollin/pollrdnorm (readable),

Pollout/pollwrnorm (writable),

Pollerr (Error)

The legitimate events are as follows:

The Pollin has data to read.

Pollrdnorm have normal data to read.

Pollrdband has priority data to read.

POLLPRI has urgent data to read.

Pollout write data does not cause blocking.

Pollwrnorm writing normal data does not cause blocking.

Pollwrband Write priority data does not cause blocking.

POLLMSG sigpoll messages are available.

Additionally, the following events may be returned in the revents domain:

Poller An error occurred with the specified file descriptor.

Pollhup the specified file descriptor pending event.

Pollnval The specified file descriptor is illegal.

These events do not make sense in the events field, because they are always returned from revents at the appropriate time. Using poll () and select () are different, you do not need to explicitly request an exception condition report.

Pollin | Pollpri is equivalent to the Read event of select (),

Pollout | Pollwrband is equivalent to the Write event of select ().

Pollin equivalent to Pollrdnorm | Pollrdband,

And Pollout is equivalent to Pollwrnorm.

If you are interested in more than one event on a descriptor, you can make a bitwise OR operation between these constant tags.

For example, if you are interested in reading, writing, and exception events on the socket descriptor FD, you can do this:

struct POLLFD FDS;

Fds[nindex].events=pollin | Pollout | Pollerr;

When the poll () function returns, you can do this by judging the event that occurs on the socket descriptor being detected:

struct POLLFD FDS;

To detect a read TCP connection request:

if ((fds[nindex].revents & pollin) = = Pollin) {//Receive data/Call accept () Receive connection request}

Detection can be written:

if ((fds[nindex].revents & pollout) = = Pollout) {//Send data}

Detecting Exceptions:

if ((fds[nindex].revents & pollerr) = = Pollerr) {//exception handling}

nfds_t Nfds : The total number of structure elements used to mark the array FDS;

Timeout : is the time of the poll function call blocking, in milliseconds;

If timeout==0, then the poll () function returns immediately without blocking,

If Timeout==inftim, then the poll () function will block until the event of interest on the socket descriptor being detected is returned, and if the event of interest never occurs, then poll () will block forever;

3. Return value:

>0: The total number of socket descriptors in the array FDS that are ready for read, write, or error states;

==0: The array FDS does not have any socket descriptors ready to read, write, or error, at which time the poll times out, the timeout is timeout milliseconds, in other words, if no event occurs on the detected socket descriptor, then poll () function blocks the millisecond length specified by timeout and returns,

The -1:poll function call fails, and the global variable Errno;errno is automatically set to one of the following values:

4. Error codes

EBADF the file descriptor specified in one or more structs is invalid.

The address that the Efaultfds pointer points to exceeds the address space of the process.

Eintr the requested event before generating a signal that the call can be re-initiated.

The Einvalnfds parameter exceeds the Plimit_nofile value.

Enomem There is not enough memory available to complete the request.

5. Implementation mechanism

Poll is a system call, its kernel entry function for sys_poll,sys_poll almost nothing to do any processing directly calls Do_sys_poll,do_sys_poll execution process can be divided into three parts:

1), copies the user's incoming POLLFD array to the kernel space, so the copy operation is related to the group length, which is an O (n) operation in the time, and the code for this step includes the part from the beginning of the function to the do_poll before the call to the Do_sys_poll.

2), query each file descriptor for the status of the device, and if the device is not ready, add an entry in the device's wait queue and continue to query the status of the next device. If no device is ready after querying all the devices, then the current process needs to be suspended until the device is ready or timed out, and the suspend operation is performed by calling Schedule_timeout. After the device is ready, the process is notified to continue running, and then traverses all the devices again to find the ready device. This step is due to two traversal of all devices, and the time complexity is O (n), where the wait time is not included. The relevant code is in the Do_poll function.

3), the time complexity of transferring the obtained data to the user space and performing the operations such as freeing the memory and stripping the waiting queue, and so on, is the same as O (n), and the specific code includes the part of the Do_sys_poll function that calls Do_poll to the end.

6. Precautions

1). The poll () function is not affected and constrained by the o_ndelay tag and the o_nonblock tag on the socket descriptor, that is, the poll () function will not be affected, regardless of whether the socket is blocked or non-blocking;

2). The poll () function is supported only by individual operating systems (e.g. SunOS, Solaris, AIX, HP, but not supported by Linux), and portability is poor;

7. Example 7.1. Example One
#include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <poll.h>/* int poll (struct POLLFD *fds, nfds_t nfds, int timeout);         *//* struct POLLFD {int fd;     File descriptor short events;    Requested events short revents; Returned events}; *//* the bits and set/returned in events and revents are defined in <poll.h>:P ollin:there is data to R ead. (Data readable) Pollout:writing now would not block. (Data readable) */#define OPEN_FLAGS o_rdwr|    O_creat#define open_mode 00777#define w_data "Howaylee" int main (int argc, char* argv[]) {int ret =-1;    int fd1 =-1;    int fd2 =-1;    Char r_buf[12] = {0};    struct POLLFD fds[2] = {0};    Open FD1 fd1 = open (Argv[1], open_flags, Open_mode);        if ( -1 = = fd1) {perror ("Open fd1 failed:");    return-1;    }//write FD1 ret = write (fd1, w_data, sizeof (W_data));  if ( -1 = = ret)  {perror ("Write Fd1 failed:");    Goto _out;    }//lseek fd1 head ret = lseek (fd1, 0, Seek_set);        if ( -1 = = ret) {perror ("Lseek Fd1 failed:");    Goto _out;    }//open fd2 fd2 = open (argv[2], open_flags, Open_mode);        if ( -1 = = fd2) {perror ("Open Fd2 failed:");    return-1;        }/* Blocking, waiting for program read and write operations */while (1) {//Initialize POLLFD FDS[0].FD = fd1;        Readable fds[0].events = Pollin;        FDS[1].FD = FD2;        Writable fds[1].events = pollout;        Poll ret = poll (FDS, sizeof (FDS)/sizeof (Fds[0]),-1);            if ( -1 = = ret) {perror ("poll failed:");        Goto _out; }//read fd1 if (fds[0].revents & Pollin) {//Empty cache//memset (r_buf, 0, Sizeo            F (r_buf));            ret = Read (FD1, r_buf, sizeof (R_BUF));                if ( -1 = = ret) {perror ("poll read failed:");         Goto _out;   } printf ("read =%s\n", r_buf);            }//write fd2 if (fds[1].revents & pollout) {ret = write (fd2, r_buf, sizeof (R_BUF));                if ( -1 = = ret) {perror ("poll write Failed:");            Goto _out;        } printf ("Write =%s\n", r_buf);    }}//close fd1 fd2 close (FD1);   Close (FD2); _out:return ret;}

7.2. Example II
int read_time (int fd, void *buf, int size, int ms) {ssize_t len = 0;    int ttl = 16;    struct POLLFD PFD;    int i;        while (1) {pfd.fd = FD; pfd.events = Pollin | Pollerr | Pollhup |        Pollnval;        errno = 0;        i = Poll (&AMP;PFD, 1, MS);                            if (I < 0) {if (errno = = eintr) {if (--ttl<=0) {Ls_log (Log_level_error, "[Readn_ex]readn poll ttl overflow, errno:%d size:%d", errno, si                    Ze);                return-6;            } continue;            } ls_log (Log_level_error, "[Readn_ex]readn errno:%d", errno);  return-1;            Error} else if (0==i) {Ls_log (Log_level_error, "[READN_EX]READN Poll timeout");        Return-2; } if (Pfd.revents & (Pollerr | Pollhup | Pollnval) {Ls_log (Log_level_error, "[Readn_ex]readn err revents:%x Errno:%d len:%d ", pfd.revents, errno, size);        return-3;        } len = Read (FD, (char*) buf, size);                    if (Len < 0) {if (errno = = eintr) {if (--ttl<=0) {                    Ls_log (Log_level_error, "[Readn_ex]readn poll ttl overflow, errno:%d size:%d", errno, size);                return-6;            } continue;        } return-4;         } if (len = = 0)//eof, is return-5 right???                     {Ls_log (Log_level_info, "[READN_EX] EOF");         return-5;     } return len; } return-1;}

Note: This article is not original, but the collation of a number of network materials!

"Go" Linux system I/O Multiplexing Technology II: Poll ()--good

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.