When writing programs, we often use timers. First, let’s take a look at the prototype of the select function as follows:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
Parameter description:
The first parameter nfds of slect is the maximum descriptor value in the fdset set plus 1. fdset is a bit array with a size limit of __FD_SETSIZE (1024). Each bit of the bit array represents whether its corresponding descriptor needs to be checked.
The second, third and fourth parameters of select represent an array of file descriptor bits that need to pay attention to read, write, and error events. These parameters are both input parameters and output parameters, and may be modified by the kernel to indicate which descriptors have the event of attention. Therefore, fdset needs to be reinitialized before each call to select.
The timeout parameter is the timeout time, and the structure will be modified by the kernel, and its value is the time remaining for the timeout.
To implement a timer using select, you need to use its timeout parameter, note:
1) The select function uses a structure timeval as its parameter.
2) The select function will update the value of timeval, and the value maintained by timeval is the remaining time.
If we specify the value of the parameter timeval and set the other parameters to 0 or NULL, then the select function returns after the time is exhausted. Based on this, we can use select to achieve precise timing.
The structure of timeval is as follows:
struct timeval{
long tv_sec;/*secons*
long tv_usec;/*microseconds*/
}
We can see that it is accurate to microseconds, that is, subtle.
1. Second-level timer
void seconds_sleep(unsigned seconds){
struct timeval tv;
tv.tv_sec=seconds;
tv.tv_usec=0;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
2. Millisecond level timer
void milliseconds_sleep(unsigned long mSec){
struct timeval tv;
tv.tv_sec=mSec/1000;
tv.tv_usec=(mSec%1000)*1000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
3. Subtle level timer
void microseconds_sleep(unsigned long uSec){
struct timeval tv;
tv.tv_sec=uSec/1000000;
tv.tv_usec=uSec%1000000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
Now let’s write a few lines of code to see the timing effect.
#include <>
#include <sys/>
#include <>
int main()
{
int i;
for(i=0;i<5;++i){
printf("%d\n",i);
//seconds_sleep(1);
//milliseconds_sleep(1500);
microseconds_sleep(1900000);
}
}
Note: Although a subtle level of resolution is specified in the timeval structure, the kernel supports the difference rate not so high. Many unix kernels round the timeout value up to multiples of 10ms. In addition, with the kernel scheduling delay phenomenon, that is, after the timer time reaches, the kernel needs to spend a certain amount of time to schedule the operation of the corresponding process. Therefore, the accuracy of the timer is ultimately determined by the kernel-supported discrete rate.
Category: Linux
Copy the codeThe code is as follows:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
Parameter description:
The first parameter nfds of slect is the maximum descriptor value in the fdset set plus 1. fdset is a bit array with a size limit of __FD_SETSIZE (1024). Each bit of the bit array represents whether its corresponding descriptor needs to be checked.
The second, third and fourth parameters of select represent an array of file descriptor bits that need to pay attention to read, write, and error events. These parameters are both input parameters and output parameters, and may be modified by the kernel to indicate which descriptors have the event of attention. Therefore, fdset needs to be reinitialized before each call to select.
The timeout parameter is the timeout time, and the structure will be modified by the kernel, and its value is the time remaining for the timeout.
To implement a timer using select, you need to use its timeout parameter, note:
1) The select function uses a structure timeval as its parameter.
2) The select function will update the value of timeval, and the value maintained by timeval is the remaining time.
If we specify the value of the parameter timeval and set the other parameters to 0 or NULL, then the select function returns after the time is exhausted. Based on this, we can use select to achieve precise timing.
The structure of timeval is as follows:
Copy the codeThe code is as follows:
struct timeval{
long tv_sec;/*secons*
long tv_usec;/*microseconds*/
}
We can see that it is accurate to microseconds, that is, subtle.
1. Second-level timer
Copy the codeThe code is as follows:
void seconds_sleep(unsigned seconds){
struct timeval tv;
tv.tv_sec=seconds;
tv.tv_usec=0;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
2. Millisecond level timer
Copy the codeThe code is as follows:
void milliseconds_sleep(unsigned long mSec){
struct timeval tv;
tv.tv_sec=mSec/1000;
tv.tv_usec=(mSec%1000)*1000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
3. Subtle level timer
Copy the codeThe code is as follows:
void microseconds_sleep(unsigned long uSec){
struct timeval tv;
tv.tv_sec=uSec/1000000;
tv.tv_usec=uSec%1000000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
Now let’s write a few lines of code to see the timing effect.
Copy the codeThe code is as follows:
#include <>
#include <sys/>
#include <>
int main()
{
int i;
for(i=0;i<5;++i){
printf("%d\n",i);
//seconds_sleep(1);
//milliseconds_sleep(1500);
microseconds_sleep(1900000);
}
}
Note: Although a subtle level of resolution is specified in the timeval structure, the kernel supports the difference rate not so high. Many unix kernels round the timeout value up to multiples of 10ms. In addition, with the kernel scheduling delay phenomenon, that is, after the timer time reaches, the kernel needs to spend a certain amount of time to schedule the operation of the corresponding process. Therefore, the accuracy of the timer is ultimately determined by the kernel-supported discrete rate.
Category: Linux