Three simple ways to implement timers under linux

Table of contents

1. sleep() and usleep()

1.sleep()

2.usleep()

3. Millisecond delay

2. Signal and alarm()

3. select

4. Some conclusions


1. sleep() and usleep()

        The advantage is that it is simple and convenient, and it can be called directly, but the disadvantage is also obvious, the precision is not enough, especially when the system load is relatively large, timeout phenomenon will occur.

1.sleep()

#include <unistd.h>

unsigned int sleep(unsigned int   seconds);

Function: Execution suspends for the specified number of seconds

        sleep() can only be accurate to the second level. sleep() is not a system call, and sleep() is implemented in a library function. It uses alarm() to set the alarm time, and uses sigsuspend() to suspend the process on the signal SIGALARM. sleep() will suspend the current process until the time specified by the parameter seconds is reached, or it is interrupted by a signal.

2.usleep()

#include <unistd.h>

void usleep(int     micro_seconds);

Function: Suspend the process for a period of time, the unit is microseconds (one millionth)

        It is similar to sleep() in use except that the time unit is microseconds. But the implementation is different, sleep is implemented with alarm, so the time unit is s, and the time unit of usleep is us, it is definitely not implemented by alarm, so their implementations are different, but they are all used by linux, and window It cannot be used under, because both sleep and usleep are defined under unistd.h.

        In general, when the delay time is on the order of seconds, use the sleep() function as much as possible. If the delay time is tens of milliseconds (1ms = 1000us), or less, use the usleep() function as much as possible. Only in this way can the CPU time be optimally utilized.

3. Millisecond delay

        Because there is no ready-made millisecond-level delay under linux, here we can simply write one by ourselves:

#include <unistd.h>

void msleep(unsigned long     ms)
{
    struct timeval        tv;
    tv.tv_sec = ms/1000;
    tv.tv_usec = (ms%1000)*1000;

    select(0, NULL, NULL, NULL, &tv);
}

2. Signal and alarm()

        Use the signal function to set the processing function of SIGALRM, and then use alarm() to send SIGALRM regularly to achieve.  

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int alarm_flag=1;

void timer(int sig)
{
    if(SIGALRM == sig)
    {
        alarm_flag = 1;
    }
    return;
}

int main()
{
    signal(SIGALRM, timer);
    
    while( alrm_flag )
    {
        alarm_flag = 0;

        printf("hello\n");
        alarm(5);
     }

    return 0;
}

#include <unistd.h>

unsigned int alarm(unsigned int         seconds);        

Function: set signal transmission alarm clock

        alarm() is also called the alarm clock function. The main function of the alarm() function is to set the signal transmission alarm clock, that is, to set the signal SIGALRM to be sent to the current process after the number of seconds passed by the parameter seconds. If the processing function of the signal SIGALARM is not set, then alarm() will terminate the process by default. If the parameter seconds is 0, the previously set alarm clock will be canceled and the remaining time will be returned.

        PS: A process can only have one alarm time. If the alarm time has been set before calling alarm, any previous alarm time will be replaced by the new value.

3. select

#include <sys/select.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval * timeout);

Function: used to wait for the status change of the file descriptor. The parameter n represents the largest file descriptor plus 1, and the parameters readfds, writefds and exceptfds are called descriptor groups, which are used to return the read, write or exception status of the descriptor.

         The parameters and functions of the select function will not be introduced in detail here, and you can check them out if you are interested. If you want to implement a timer here, set the first parameter to 0, set the middle three file descriptor sets to NULL, and the fifth parameter is the time structure. We mainly use the parameter and set it to what we want Timing frequency is fine.

        timeout is the structure timeval, which is used to set the waiting time of select(), and its structure is defined as follows:

struct timeval

{

        time_t        tv_sec;

        time_t        tv_usec;
};

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

void timer_s(unsigned long    s, unsigned long     us)
{
    struct timeval        tv;

    tv.tv_sec = s;
    tv.tv_usec = us;

    select(0, NULL, NULL, NULL, &tv);
}

int main()
{
    while(1)
    {
        printf("hello\n");
        timer_s(3, 0);
    }

    return 0;
}

4. Some conclusions

        Everyone chooses according to their own needs. This is a picture picked up from the Internet. The link to the original text is as follows:

Different sleep methods of sleep, usleep, nanosleep, poll and select in Linux https://mp.weixin.qq.com/s?src=11×tamp=1680196399&ver=4438&signature=LzDVJT7uLU7DuxA6qxK8Sm4FqjJw8G347mhB56nkDIb5R2XQs ifqz-NFi1nmisdVYxrrRNgLVKIJqjN4koJ59oTtTBWunbaWVMV7u6dNydmBRf-DA9aR6yVNKkbJF*oI&new=1

Guess you like

Origin blog.csdn.net/qq_51368339/article/details/129870386