Linux 延时函数 nanosleep、select比较

文章展示了如何使用Linux系统调用select和nanosleep来实现毫秒级的延时。select函数在循环中需要注意tv结构体的重新初始化,而nanosleep则提供了更为精确的延时控制。在实际测试中,select的延时存在约1ms的误差。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <signal.h>
#include <time.h>//必须调用这俩头文件
#include <sys/time.h>
#include "sys/select.h" //必须调用这俩头文件

// 获取毫秒级时间格式
void get_format_time_ms(char *str_time)
{
    struct tm *tm_t;
    struct timeval time;
    gettimeofday(&time, NULL);
    tm_t = localtime(&time.tv_sec);
    if (NULL != tm_t)
    {
        sprintf(str_time, "%04d-%02d-%02d %02d:%02d:%02d.%03ld",
                tm_t->tm_year + 1900,
                tm_t->tm_mon + 1,
                tm_t->tm_mday,
                tm_t->tm_hour,
                tm_t->tm_min,
                tm_t->tm_sec,
                time.tv_usec / 1000);
    }

    return;
}

void usleep_slect(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);
}

int main(int argc, char *argv[])
{
   // 使用select
    char _Time_S_M[25];
    struct timeval delay;
    while (1)
    {
        // delay.tv_sec = 0;
        // delay.tv_usec = 5 * 1000; // 5ms
        // select(0, NULL, NULL, NULL, &delay);
        usleep_slect(5 * 1000);// 5ms
        get_format_time_ms(_Time_S_M);
        printf("当前时间=[%s]\n", _Time_S_M);
    }
    // 使用nanosleep
    // struct timespec ts, ts1;  
    // ts.tv_nsec = 5 * 1000 * 1000; // 5ms ,  纳秒
    // ts.tv_sec = 0;// 秒
    // while (1)
    // {
    //     get_format_time_ms(_Time_S_M);
    //     printf("当前时间=[%s]\n", _Time_S_M);
    //  
    //     if (nanosleep(&ts, &ts1) == -1)
    //     {
    //         printf("error!\n");
    //         exit(1);
    //     }
    // }

    return 0;
}

几个注意事项:

1、tv_sec的初始化最好在tv_usec的前面

2、select的延时时间等于sec和usec时间之和

3、不知为啥,select的延时时间与设定值有1ms左右的误差

  1. select每次运行之后,会将tv的值清零,所以如果要循环使用select,务必把tv.tv_usec的初始化放在循环中!

最后测试时候 ,设定5毫秒,但是有时候会1ms左右的误差。不知道为什么

测试结果如下

当前时间=[2023-02-20 16:08:45.265]

当前时间=[2023-02-20 16:08:45.270]

当前时间=[2023-02-20 16:08:45.276]

当前时间=[2023-02-20 16:08:45.282]

当前时间=[2023-02-20 16:08:45.287]

当前时间=[2023-02-20 16:08:45.293]

当前时间=[2023-02-20 16:08:45.298]

当前时间=[2023-02-20 16:08:45.303]

当前时间=[2023-02-20 16:08:45.309]

当前时间=[2023-02-20 16:08:45.315]

当前时间=[2023-02-20 16:08:45.321]

当前时间=[2023-02-20 16:08:45.326]

当前时间=[2023-02-20 16:08:45.331]

当前时间=[2023-02-20 16:08:45.337]

当前时间=[2023-02-20 16:08:45.342]

当前时间=[2023-02-20 16:08:45.347]

当前时间=[2023-02-20 16:08:45.352]

当前时间=[2023-02-20 16:08:45.358]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值