linux下实现定时器的三种简单方式

目录

一. sleep()和usleep()

1.sleep()

2.usleep()

3.毫秒级延时

二. signal与alarm()

三. select

四. 一些总结


一. sleep()和usleep()

        优点是简单便捷,直接调用即可,但是缺点也很明显,精度不够,特别是在系统负载比较大时,会发生超时现象。

1.sleep()

#include <unistd.h>

unsigned int sleep(unsigned int   seconds);

功能:执行挂起指定的秒数

        sleep()只能精确到秒级上。sleep()非系统调用,sleep()是在库函数中实现的,它是通过alarm()来设定报警时间,使用sigsuspend()将进程挂起在信号SIGALARM上。sleep()会令目前的进程暂停,直到达到参数seconds 所指定的时间,或是被信号所中断。

2.usleep()

#include <unistd.h>

void usleep(int     micro_seconds);

功能:把进程挂起一段时间,单位是微秒(百万分之一)

        除了时间单位为微秒以外,在使用上与sleep()差不多。但实现是不同的,sleep是用alarm实现的,所以时间单位为s ,而usleep的时间单位为us,肯定不是由alarm实现的,所以说它们的实现不同,但都是linux用的,而window下不能用,因为都是sleep和usleep都是在unistd.h下定义的。

        一般情况下,延迟时间数量级是秒的时候,尽可能使用sleep()函数。如果延迟时间为几十毫秒(1ms = 1000us),或者更小,尽可能使用usleep()函数。这样才能最佳的利用CPU时间。

3.毫秒级延时

        因为linux下没有现成的毫秒级延时,这里我们可以自己简单写一个:

#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);
}

二. signal与alarm()

        使用signal函数设定SIGALRM的处理函数,然后使用alarm()定时发送SIGALRM来实现。  

#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);        

功能:设置信号传送闹钟

        alarm()也称为闹钟函数,alarm()函数的主要功能是设置信号传送闹钟,即⽤来设置信号SIGALRM 在经过参数seconds 秒数后发送给⽬前的进程。如果未设置信号SIGALARM 的处理函数,那么alarm()默认处理终⽌进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。

        PS:一个进程只能有一个闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。

三. 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);

功能:用来等待文件描述词状态的改变。参数n代表最大的文件描述词加1,参数readfds、writefds 和exceptfds称为描述词组,是用来回传该描述词的读,写或例外的状况。

         这里就不详细介绍select函数的参数及功能了,大家感兴趣可以自行查阅。这里要实现定时器的话,把第一个参数设置为0,中间三个文件描述符集都设置为NULL,第五个参数为时间结构体,我们主要就是使用参数,把它设置为我们想要定时的频率就好。

        timeout为结构timeval,用来设置select()的等待时间,其结构定义如下:

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;
}

四. 一些总结

        大家根据自己需求选择,这是在网上扒下来的一张图,原文链接如下:

Linux中的sleep、usleep、nanosleep、poll和select不同的sleep方式https://mp.weixin.qq.com/s?src=11×tamp=1680196399&ver=4438&signature=LzDVJT7uLU7DuxA6qxK8Sm4FqjJw8G347mhB56nkDIb5R2XQsifqz-NFi1nmisdVYxrrRNgLVKIJqjN4koJ59oTtTBWunbaWVMV7u6dNydmBRf-DA9aR6yVNKkbJF*oI&new=1

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux系统提供了多种方法实现定时器,其中常用的有以下两种方式: 1. 使用系统调用函数 setitimer() setitimer() 函数可以设置定时器,它有三个参数:定时器类型、定时器的初始值和定时器的重载值。使用该函数需要引入头文件 <sys/time.h>。 示例代码: ``` #include <sys/time.h> #include <signal.h> #include <stdio.h> #include <unistd.h> void timer_handler(int signum) { printf("Timer expired.\n"); } int main() { struct sigaction sa; struct itimerval timer; /* 安装信号处理器 */ sa.sa_handler = timer_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGALRM, &sa, NULL); /* 设置定时器 */ timer.it_value.tv_sec = 5; /* 初始值为5秒 */ timer.it_value.tv_usec = 0; timer.it_interval.tv_sec = 1; /* 重载值为1秒 */ timer.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &timer, NULL); /* 等待定时器触发 */ while (1) { sleep(1); } return 0; } ``` 2. 使用Linux内核提供的定时器接口 Linux内核提供了一组定时器接口,可以用于实现高精度、高可靠性的定时器。使用该定时器需要引入头文件 <linux/timer.h>。 示例代码: ``` #include <linux/timer.h> #include <linux/jiffies.h> #include <linux/module.h> static struct timer_list my_timer; void my_timer_callback(unsigned long data) { /* 定时器到期时执行的函数 */ printk("Timer expired.\n"); /* 重新设置定时器 */ mod_timer(&my_timer, jiffies + msecs_to_jiffies(5000)); } int init_module() { /* 初始化定时器 */ init_timer(&my_timer); my_timer.function = my_timer_callback; my_timer.expires = jiffies + msecs_to_jiffies(5000); /* 初始值为5秒 */ add_timer(&my_timer); return 0; } void cleanup_module() { /* 删除定时器 */ del_timer(&my_timer); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值