Select () Functions and fd_zero, fd_set, fd_clr, and fd_isset

Source: Internet
Author: User







 

From: http://hi.baidu.com/bimufo/item/139700e4d880cba1c00d755c

The select function is used in non-blocking scenarios. When a socket or a set of sockets have signals, the system provides the select function to achieve multiplexing of input/output models. prototype:
# Include <sys/time. h>
# Include <unistd. h>


Int select (INT maxfd, fd_set * rdset, fd_set * wrset, fd_set * exset, struct timeval * timeout );
The maxfd parameter is the maximum file descriptor value to be monitored plus 1. rdset, wrset, and exset correspond to the set of readable file descriptors to be detected, respectively, set of writable file descriptors and the set of abnormal file descriptors. The struct timeval structure is used to describe the length of a period of time. If no event occurs in the descriptor to be monitored during this time, the function returns and the return value is 0.
Fd_set is a collection of file descriptors (FD). It represents an FD with one digit (which will be described in detail below ), for the fd_set type, use the following four macros:
Fd_zero (fd_set * fdset); clears the specified file descriptor set. Initialization is required before setting the file descriptor set, the result is unknown because the system usually does not clear the memory space after it is allocated.
Fd_set (int fd, fd_set * fdset); used to add a new file descriptor to the file descriptor set.
Fd_clr (int fd, fd_set * fdset); used to delete a file descriptor in the file descriptor set.
Fd_isset (int fd, fd_set * fdset); used to test whether the specified file descriptor is in this set.
In the past, an fd_set usually only contains <32 FD (File description), because fd_set actually only uses a 32-bit vector to represent FD. Now, in Unix systems, the header file <sys/select. h> defines the constant fd_setsize, which is the number of descriptive words of the Data Type fd_set. The value is usually 1024, which indicates the FD of <1024. Based on the bit vector Implementation of fd_set, we can re-understand the four macros that operate fd_set:
Fd_set set;
Fd_zero (& set );
Fd_set (0, & set );
Fd_clr (4, & set );
Fd_isset (5, & set );
―――――――――――――――――――――――――――――――――――――――
Note that the maximum value of FD must be <fd_setsize.
―――――――――――――――――――――――――――――――――――――――

The select function interface is relatively simple:
Int select (INT NFDs, fd_set * readset, fd_set * writeset, fd_set * reset tset, struct Tim * timeout );

Function:
Test the specified FD readable? Writable? Are there any exception conditions to be processed?
Parameters:

-- NFDs
The number of file description words to be checked (that is, the number of characters in fd_set). The value should be greater than the maximum FD value contained in the three fd_set groups, it is generally set to the maximum FD value included in the three fd_set groups plus 1 (for example, if the maximum FD value in readset, writeset, and javastset is 5, then NFDs = 6, because FD starts from 0 ). Set this value to improve efficiency so that the function does not have to check all 1024 bits of fd_set.
-- Readset
A group of file description words used to check readability.
-- Writeset
A group of file descriptions used to check the writability.
-- Effectset
The file description used to check whether any exception condition exists. (Note: errors are not included in the exception conditions)
-- Timeout
It is used to describe a period of time. If no event occurs in the descriptor to be monitored during this period, the function returns and the return value is 0.
There are three possibilities:
1. Timeout = NULL (blocking: select will be blocked until an event occurs on a file descriptor)
2. The structure pointed to by timeout is set to a non-zero time (wait for a fixed time: if an event occurs or the time is exhausted within the specified time period, the function returns)
3. The structure pointed to by timeout. The time is set to 0 (non-blocking: Only checks the state of the descriptor set, and then returns immediately without waiting for the occurrence of external events)

Return Value:
Returns the total number of FD instances whose corresponding bits are still 1.

Remarks:
All three fd_sets set 0 for some FD locations. Only the readable, writable, and exceptional FD bits to be processed are still 1.

For example, for Recv (), when no data comes to call it, your thread will be blocked. If data never comes, your thread will be blocked for a long time. this is obviously not good.
Therefore, select is used to check whether the set of characters are readable (that is, whether data is read)
The procedure is as follows --
Socket S;
.....
Fd_set set;
While (1)
{
Fd_zero (& set); // clear your set of characters
Fd_set (S, & set); // Add the set of characters you are interested in to the set. Here is the set of characters s for reading data.
Select (0, & set, null); // check whether the set of characters are readable,
// In many cases, whether there is data (note, but in many cases)
// Whether the SELECT statement has an error and is not written
If (fd_isset (S, & set) // check whether s is in this set,
{// Select will update this set and remove unreadable sets of Characters
// Only the qualified characters are retained in this set.
Recv (S ,...);
}
// Do something here
}

The key to understanding the select model is to understand fd_set. For convenience, the length of fd_set is 1 byte. Each bit in fd_set can correspond to a file descriptor FD. The fd_set with a length of 1 byte can correspond to a maximum of 8 FD.
(1) execute fd_set set; fd_zero (& set); then set uses bits to indicate that it is 00.
(2) If FD = 5, execute fd_set (FD, & set); then set to 0001,0000 (5th position is 1)
(3) If FD = 2 or FD = 1 is added, Set Becomes 0001,0011.
(4) execute select (6, & set, 0, 0) to block the wait
(5) If both FD = 1 and FD = 2 have readable events, select returns, and set changes. Note: FD = 5 where no event occurs is cleared.
Based on the above discussion, we can easily draw the features of the select model:
(1) the number of monitored file descriptors depends on the value of sizeof (fd_set. Sizeof (fd_set) = 512 on my server. Each bit represents a file descriptor. The maximum file descriptor supported on my server is 512x8 = 4096. It is said to be adjustable. It is also said that although it is adjustable, the adjustment ceiling is determined by the variable value during kernel compilation. I am not very interested in adjusting the fd_set size. For details, see http://www.cppblog.com/cpp%e/archive/2008/03/21/41061.htmlmodel 2 (1), which can effectively break through the file descriptor limit that can be monitored by select.
(2) When FD is added to the select monitoring set, another data structure array must be used to store FD in the select monitoring set. The first is used to return the result after the SELECT statement, array is used as the source data and fd_set for fd_isset judgment. Second, after the SELECT statement is returned, the previously added but no event occurs in FD will be cleared, and the FD will be re-obtained from the array one by one before each start of the SELECT statement (fd_zero first ), scans the array and obtains the maximum FD value maxfd, which is used as the first parameter of select.
(3) it can be seen that the select model must loop array (add FD, take maxfd) before Select, And Then loop array (fd_isset to determine whether a time has occurred) After Select returns ).
The following is a pseudo code that describes the server model of the basic select model:
Array [slect_len];
Nsock = 0;
Array [nsock ++] = listen_fd; (previously, the listen port was bound and listen)
Maxfd = listen_fd;
While {
Fd_zero (& set );
Foreach (FD in array)
{
If FD is greater than maxfd, maxfd = FD
Fd_set (FD, & set)
}
Res = select (maxfd + 1, & set, 0, 0 );
If (fd_isset (listen_fd, & set ))
{
Newfd = accept (listen_fd );
Array [nsock ++] = newfd;
If (-- res = 0) continue
}
Foreach subscript 1 (FD in array)
{
If (fd_isset (FD, & set ))
Perform read and other operations
If it is incorrect or disabled, delete the FD and swap the corresponding position in the array with the last element. nsock minus one.
If (-- res = 0) continue
}
}
The process of using the select function is generally:
First, call the macro fd_zero to clear the specified fd_set, then call the macro fd_set to add the FD to be tested to fd_set, and then call the select function to test all FD in fd_set, finally, use the macro fd_isset to check whether the corresponding bit is still 1 after a FD is called by the Select function.

The following is an example of testing the readability of descriptive words in a single file:
Int isready (int fd)
{
Int RC;
Fd_set FDS;
Struct Tim 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) // Error
Return-1;
Return fd_isset (FD, & FDs )? 1: 0;
}
The following is a complex application:
// This Code specifies the readability and writability of the socket description, because the socket uses FD
Uint32 socketwait (tsocket * s, bool Rd, bool WR, uint32 timems)
{
Fd_set rfds, wfds;
# Ifdef _ Win32
Tim TV;
# Else
Struct Tim TV;
# Endif
Fd_zero (& rfds );
Fd_zero (& wfds );
If (RD) // true
Fd_set (* s, & rfds); // Add the description to be tested
If (WR) // false
Fd_set (* s, & wfds );
TV. TV _sec = timems/1000; // second
TV. TV _usec = timems % 1000; // MS
For (;) // If errno = eintr, repeatedly test the readability of the buffer.
Switch (select (* s) + 1, & rfds, & wfds, null,
(Timems = time_infinite? Null: & TV) // test whether the interface receives data in the buffer zone within the specified time.
{// 0 -- timeout,-1 -- Error
Case 0:
Return 0;
Case (-1 ):
If (socketerror () = eintr)
Break;
Return 0; // error, but not eintr
Default:
If (fd_isset (* s, & rfds) // If S is a member of FDS, non-0 is returned; otherwise, 0 is returned.
Return 1;
If (fd_isset (* s, & wfds ))
Return 2;
Return 0;
};
}

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.