[Convert] Select and poll

Source: Internet
Author: User

How to manage multiple connections?
"What should I do if I want to monitor more than one file descriptor (FD)/connection/stream at the same time ?"

Use the select () or Poll () function.

Note: Select () is introduced in BSD, and Poll () is the product of sysv stream flow control. Therefore, here we have considerations for porting the platform: Pure BSD systems may still lack poll (), while earlier svr3 systems may not have select (), although adding it in svr4. Currently, both are POSIX. 1g standards)

In essence, select () and Poll () do the same thing, but the method of completion is different. Both checks a set of file descriptors to check whether a specific time will occur and wait for it to happen within a certain period of time.

[Important: Neither select () nor poll () is very useful for common files. They are mainly used for socket, pipe, and Pty), the terminal device (TTY) and other character devices, but these operations are system-dependent.]

2.1.1. How do I use the select () function?
The Select () function interface is mainly based on the 'fd _ set' type. It ('fd _ set') is a collection of file descriptors (FD. Because the length of the fd_set type varies on different platforms, a set of standard macro definitions should be used to process such variables:

Fd_set set;
Fd_zero (& set);/* clears the set */
Fd_set (FD, & set);/* Add FD to set */
Fd_clr (FD, & set);/* clear FD from set */
Fd_isset (FD, & set);/* If FD is true in Set */

In the past, an fd_set usually only contains less than or equal to 32 file descriptors, because fd_set actually uses only one int bit vector. In most cases, checking that fd_set can include any value of the file descriptor is the responsibility of the system, but determining how much your fd_set can put sometimes you should check/modify the value of the macro fd_setsize. * This value is related to the system. * Check the man manual of select () in your system. Some systems have problems with support for more than 1024 file descriptors. [Translator's note: Linux is such a system! You will find that the result of sizeof (fd_set) is 128 (* 8 = fd_setsize = 1024), although this rarely happens to you.]

The basic Select Interface is very simple:

Int select (INT NFDs, fd_set * readset, fd_set * writeset,
Fd_set * effectset, struct timeval * timeout );

Where:

NFDs
Number of file descriptors to be checked. The value must be the largest among the three fd_sets.
Larger, not the total number of actual file descriptors.
Readset
A set of file descriptors used to check readability.
Writeset
A set of file descriptors used to check the writability.
Effectset
The file descriptor used to check the unexpected state. (Note: errors are not unexpected)
Timeout
Null Pointer indicates infinite waiting; otherwise, it is a pointer to the timeval structure, representing
Long wait time. (If both TV _sec and TV _usec are equal to 0, the file descriptor
Is not affected, but the function is not suspended)

The function returns the total number of Operation file descriptors corresponding to the response operation, and the three groups of data are modified at the appropriate position. Only some of the response operations are not modified. Then we should use the fd_isset macro to find the returned file descriptor group.

Here is a simple example of testing the readability of a single file descriptor:

Int isready (int fd)
{
Int RC;
Fd_set FDS;
Struct timeval TV;

Fd_zero (& FDs );
Fd_set (FD, & FDs );
TV. TV _sec = TV. TV _usec = 0;

Rc = select (FD + 1, & FDS, null, null, & TV );
If (RC <0)
Return-1;

Return fd_isset (FD, & FDs )? 1: 0;
}

Of course, if we pass the NULL pointer As fd_set, it means we are not interested in this operation, but select () will still wait until it occurs or exceeds the waiting time.

[Note: In Linux, timeout refers to the time spent by the program in a non-sleep state, rather than the actual past time, this will cause non-Linux platform porting time issues. Porting also involves that in the system v style, select () sets timeout to an undefined null state before exiting the function, but not in BSD, linux follows System V at this point, so you should pay attention to the reuse of the timeout pointer.]

2.1.2. How do I use poll ()?
Poll () accepts a pointer pointing to the 'struct pollfs' list, including the file descriptor and events you want to test. The event is determined by the bit mask of the event domain in the structure. The current structure will be filled in after the call and returned after the event occurs. The "poll. H" file in svr4 (possibly earlier versions) contains macro definitions used to determine events. The wait time of the event is accurate to milliseconds (but it is confusing that the wait time type is int). When the wait time is 0, the poll () function returns immediately, -1 indicates that poll () is suspended until a specified event occurs. The following is the structure of pollfd.

Struct pollfd {
Int FD;/* file descriptor */
Short events;/* Waiting events */
Short revents;/* events actually occurred */
};

Similar to select (), when a positive value is returned, it indicates the number of file descriptors meeting the event response. If 0 is returned, it indicates that no event has occurred in the specified event. If the returned result is negative, check errno immediately because an error occurs.

If no event occurs, the revents will be cleared.

Here is an example

/* Detects two file descriptors, which are general data and high-priority data. If an event occurs
Then the handler () function is called with correlation Descriptor and priority, and there is no time limit to wait
The error occurs or the descriptor is suspended. */

# Include <stdlib. h>
# Include <stdio. h>

# Include <sys/types. h>
# Include <stropts. h>
# Include <poll. h>

# Include <unistd. h>
# Include <errno. h>
# Include <string. h>

# Define normal_data 1
# Define hipri_data 2

Int poll_two_normal (INT fd1, int fd2)
{
Struct pollfd poll_list [2];
Int retval;

Poll_list [0]. FD = fd1;
Poll_list [1]. FD = fd2;
Poll_list [0]. Events = Pollin | pollpri;
Poll_list [1]. Events = Pollin | pollpri;

While (1)
{
Retval = poll (poll_list, (unsigned long) 2,-1 );
/* Retval is always greater than 0 or-1, because we work in blocking */

If (retval <0)
{
Fprintf (stderr, "poll error: % s/n", strerror (errno ));
Return-1;
}

If (poll_list [0]. revents & pollhup) = pollhup) |
(Poll_list [0]. revents & pollerr) = pollerr) |
(Poll_list [0]. revents & pollnval) = pollnval) |
(Poll_list [1]. revents & pollhup) = pollhup) |
(Poll_list [1]. revents & pollerr) = pollerr) |
(Poll_list [1]. revents & pollnval) = pollnval ))
Return 0;

If (poll_list [0]. revents & Pollin) = Pollin)
Handle (poll_list [0]. FD, normal_data );
If (poll_list [0]. revents & pollpri) = pollpri)
Handle (poll_list [0]. FD, hipri_data );
If (poll_list [1]. revents & Pollin) = Pollin)
Handle (poll_list [1]. FD, normal_data );
If (poll_list [1]. revents & pollpri) = pollpri)
Handle (poll_list [1]. FD, hipri_data );
}
}

2.1.3. Can I use sysv IPC and select ()/poll () at the same time ()?
* No. * (Unless on AIX, because it uses a very strange method to implement this combination)

In general, using select (), Poll (), and sysv message queues at the same time will cause a lot of trouble. Sysv IPC objects are not processed using file descriptors, so they cannot be passed to select () and Poll (). There are several solutions, with varying severity:


Completely abandon using sysv IPC. :-)

Use fork (), then let the sub-process sysv IPC, and then use the pipeline or set of interfaces to talk to the parent process. The parent process uses select ().

Same as above, but let the sub-process use select () and then communicate with the father using a message queue.

Schedule the process to send a message to you and send another signal after the message is sent. * Warning *: it is not easy to write a program that will lose messages or cause deadlocks.

There are other methods.

[Convert] Select and poll

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.