This article from the CSDN blog, reproduced please indicate the source: http://blog.csdn.net/unbutun/article/details/4722448
Round Robin Function
Concepts and functions of round robin
Applications that use non-blocking I/O usually use select () and poll (), poll, and select to query the status of the device so that the user program knows that
Whether non-blocking access can be performed on devices requires the poll function in the device driver.
The Select () and poll () system calls will eventually cause the poll () function in the device driver to be executed. Poll () function is the final execution body)
In Linux, the select call process is as follows:
1. the user-layer application calls select (), and the underlying calls poll ())
2. The core layer calls sys_select () --> do_select ()
Finally, call the poll function of struct file_operations * f_op for the struct file type variable corresponding to the file descriptor fd.
Of course, epoll () is also introduced in 2.25.45, that is, extended poll ();
The nature of select () and poll () System calls is the same. The former is introduced in bsd unix, and the latter is introduced in System V
.
1. What is a file descriptor first? What is its function?
A file descriptor is a simple integer used to indicate the files and sockets opened by each process. The first open file is 0, and the second is
1. So on. A Unix operating system usually imposes a limit on the number of files that can be opened by each process. What's more, unix usually has a system
Level.
In most cases, 1024 file descriptors are sufficient. A very busy cache may require 4096 or more. Of course, you can configure the file description by yourself.
When configuring file descriptor restrictions, we recommend that you set the number of system-level limits to twice the limit for each process.
Round-Robin programming in applications
The select () System Call introduced in bsd unix is the most widely used in applications. Its prototype is as follows:
Int select (int numfds, fd_set * readfme, fd_set * writefds, fd_set * limit TFDs, struct timeval * timeout );
The first parameter of select is the number of objects to be detected in the file descriptor set. The value must be at least 1 larger than the maximum file descriptor to be detected. The readfds Parameter
The read-monitored file descriptor set is specified. The writefds parameter specifies the write-monitored file descriptor set. The parameter specified by the except TFDs parameter is
File descriptor set of conditional monitoring.
The Timeout parameter is a pointer to the struct timeval type. It enables select () to wait for the timeout time.
Returns. The struct timeval data structure is defined as follows:
Struct timeval
{
Int TV _sec; // The number of seconds.
Int TV _usec; // indicates the number of milliseconds
};
Timeout gets different values, and the call has different properties:
1. If the value of timeout is 0, the call will return immediately;
2. If timeout is NULL, the select () call will be blocked until the file descriptor is ready. (when a file descriptor is ready
Send a signal to wake up this function .)
3. timeout is a positive integer, which is a general timer.
The return value of select is as follows:
1. Under normal circumstances, the number of ready file descriptors is returned;
2. No device is ready after the timeout duration. The returned value is 0;
3. If select is interrupted by a signal, it returns-1 and sets errno to EINTR.
4. if an error occurs,-1 is returned and the corresponding errno is set.
The select () function interface is mainly based on the "fd_set" type. This type 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 this class variable:
First, let's understand the definition of the fd_set structure.
# Define FD_ZERO (fdsetp) _ FD_ZERO (fdsetp)
(Note that the constants defined below are very useful because they are used in the fd_set structure. Of course, these values are not necessarily dead,
There are different values in different programs, but these values are only a few of the specified values)
# Define _ FDSET_LONGS (_ FD_SETSIZE/_ NFDBITS) // the calculated value is 32.
# Define _ FD_SETSIZE 1024
# Define _ NFDBITS (8 * sizeof (unsigned long) // 8*4 = 32
Typedef struct {
37 unsigned long fds_bits [_ FDSET_LONGS];
38} _ kernel_fd_set;
Typedef _ kernel_fd_set fd_set;
The above is the definition of the file descriptor set fd_set. If you can have it, I think you are more happy to learn the file descriptor:
0 |
0 |
0 |
0 |
0 |
1 |
0 |
... |
0 |
0 |
... |
0 |
1 |
0 |
0 |
... |
0 |
0 |
0 |
0 |
0th-bit 31-bit 32-bit 63-bit
The following operations are used to set, clear, and determine the set of file descriptors.
FD_ZERO (fd_set * set); // set the value in the file descriptor set fd_set to 0, so that all the corresponding bits are set to 0;
The specific operations on this function are as follows:
Static _ inline _ void _ FD_ZERO (_ kernel_fd_set * p)
88 {
89 unsigned long * tmp = p-> fds_bits;
90 int I;
91
92 if (_ builtin_constant_p (_ FDSET_LONGS )){
93 switch (_ FDSET_LONGS) {// _ FDSET_LONGS value is determined by the System
94 case 16:
95 tmp [0] = 0; tmp [1] = 0; tmp [2] = 0; tmp [3] = 0;
96 tmp [4] = 0; tmp [5] = 0; tmp [6] = 0; tmp [7] = 0;
97 tmp [8] = 0; tmp [9] = 0; tmp [10] = 0; tmp [11] = 0;
98 tmp [12] = 0; tmp [13] = 0; tmp [14] = 0; tmp [15] = 0;
99 return;
100
101 case 8:
102 tmp [0] = 0; tmp [1] = 0; tmp [2] = 0; tmp [3] = 0;
103 tmp [4] = 0; tmp [5] = 0; tmp [6] = 0; tmp [7] = 0;
104 return;
105
106 case 4:
107 tmp [0] = 0; tmp [1] = 0; tmp [2] = 0; tmp [3] = 0;
108 return;
109}
110}
111 I = _ FDSET_LONGS;
112 while (I ){
113 I --;
114 * tmp = 0;
115 tmp ++;
116} // This cycle is used to make the above judgment operations more secure.
117}
The built-in function _ builtin_constant_p is used to determine whether a value is a compilation constant. If the parameter _ FDSET_LONGS
The value is a constant, and the function returns 1; otherwise, 0 is returned.
FD_SET (int fd, fd_set * set); // Add a file descriptor to the file description set.
That is, location 1 of fd in the file descriptor, * set is the object of the operated file descriptor set.
2 static _ inline _ void _ FD_SET (unsigned long _ fd, _ kernel_fd_set * _ fdsetp)
53 {
54 unsigned long _ tmp = _ fd/_ NFDBITS;
55 unsigned long _ rem = _ fd % _ NFDBITS;
56 _ fdsetp-> fds_bits [_ tmp] | = (1UL <__rem); // shifts the 1 left _ rem bit of the unsigned long integer
57}
FD_CLR (int fd, fd_set * set) // clears a file descriptor from the file descriptor set.
Static _ inline _ void _ FD_CLR (unsigned long _ fd, _ kernel_fd_set * _ fdsetp)
61 {
62 unsigned long _ tmp = _ fd/_ NFDBITS;
63 unsigned long _ rem = _ fd % _ NFDBITS;
64 _ fdsetp-> fds_bits [_ tmp] & = ~ (1UL <__rem );
65}
FD_ISSET (int fd, fd_set * set) // checks whether the file descriptor is set.
9 static _ inline _ int _ FD_ISSET (unsigned long _ fd, const _ kernel_fd_set * _ p)
70 {
71 unsigned long _ tmp = _ fd/_ NFDBITS;
72 unsigned long _ rem = _ fd % _ NFDBITS;
73 return (_ p-> fds_bits [_ tmp] & (1UL <__rem ))! = 0;
74}
Polling in the device driver:
Unsigned int (* poll) (struct file * filp, struct poll_table * wait );
The first parameter is the file struct pointer, and the second parameter is the round table pointer. This function should perform the following two tasks.
1. Call the poll_wait () function for the waiting queue that may cause Device File status changes, and add the corresponding waiting queue header to poll_table;
2. Indicates whether to use a mask that does not block read or write access to the device.
The prototype of the key poll_wait (*) function used to register the waiting queue to poll_table is as follows:
Void poll_wait (struct file * filp, wait_queue_heat_t * queue, poll_table * wait );
Static inline void poll_wait (struct file * filp, wait_queue_head_t * wait_address, poll_table * p)
38 {
39 if (p & wait_address)
40 p-> qproc (filp, wait_address, p); // This function needs to be compiled by the user.
41}
The following is the definition of the round table:
33 typedef struct poll_table_struct {
34 poll_queue_proc qproc;
35} poll_table;
31 typedef void (* poll_queue_proc) (struct file *, wait_queue_head_t *, struct poll_table_struct *);
From the code above, we can know that the poll_table structure only encapsulates a function. More interestingly, this function establishes an actual data structure. the data structure, for poll and select, is a linked list of memory pages, which contains the poll_table_entry structure. each poll_table_entry holds the struct file and wait_queue_head_t pointer passed to poll_wait, and an associated waiting queue entry.
The following is the source code of the poll_table_entry struct:
48struct poll_table_entry {
49 struct file * filp;
50 wait_queue_t wait;
51 wait_queue_head_t * wait_address;
52};
The name of the poll_wait () function is very easy to get people wrong, thinking that it is the same as wait_event (), it will block waiting for a thing to happen,
This function will not cause blocking. The function of poll_wait () is to add the current process to the waiting list (poll_table) specified by the wait parameter.
The driver poll () function should return the retrieval status of the device resource, that is, the bitwise of macros such as POLLIN, POLLOUT, POLLPRI, POLLERR, and POLLNVAL.
The meaning of each macro indicates a state of the device. For example, POLLIN indicates that the device can read data without interruption, and POLLOUT indicates that the device can write data without interruption.
The following describes the value of the available status of the poll () function:
POLLIN
If the device can be read without blocking, this bit must be set.
POLLRDNORM
This bit must be set. If "normal" data can be read, a readable device returns (POLLIN | POLLRDNORM ).
POLLRDBAND
This bit indicates that the out-of-band data can be read from the device. Currently, it is only used in a Linux kernel (DECnet code) and is usually unavailable to the device driver.
POLLPRI
High-priority data (out-of-band) can be read without blocking. This bit causes the select Report to encounter an exception in the file because selct reports out-of-band data as an exception.
POLLHUP
When the process reading the device sees the end of the file, the driver must set POLLUP (hang-up). A select call process is notified that the device is readable, as specified by the selcet function.
POLLERR
An error has occurred on the device. When poll is called, the device is reported to be readable and writable, because all reads and writes return an error code without blocking.
POLLOUT
This bit is set in the return value if the device can be written without blocking.
POLLWRNORM
This bit has the same meaning as POLLOUT, and sometimes it is indeed the same number. A writable device returns (POLLOUT | POLLWRNORM ).
POLLWRBAND
Like POLLRDBAND, this bit indicates that data with zero priority can be written to the device. This bit is used only for poll datagram,
Because a datagram looks at data outside the conveyor belt, you should repeat POLLRDBAND and POLLWRBAND to make sense only to the file descriptor associated with the socket:
Generally, device drivers do not use these labels.