linux 内核态和用户态定时器函数使用总结

1,场景总结

定时器类型精度范围适用场景注意事项
用户态信号定时器秒级简单任务调度、心跳检测信号处理函数中不可调用非异步安全函数
timerfd+epoll纳秒级高精度事件循环、多媒体处理需要配合IO多路复用机制使用
内核timer_list毫秒级设备驱动、硬件交互基于jiffies时钟滴答
内核hrtimer微秒级实时系统、性能监控消耗更多CPU资源
用户态传统信号定时器秒级后台日志轮转、简单心跳检测等对精度要求不高的场景需要配合IO多路复用机制使用

2,用户态使用

(1),监控日志

#include <sys/time.h>
#include <signal.h>
#include <unistd.h>

void timer_handler(int sig) {
    static int count = 0;
    KEIL_LOG(KERNEL_CTRL, "Timer expired %d times\n", ++count);
    //printf("Timer expired %d times\n", ++count);
}

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

    // 配置定时器(首次1秒后触发,之后每2秒触发)
    timer.it_value.tv_sec = 1;
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 2;
    timer.it_interval.tv_usec = 0;
    
    setitimer(ITIMER_REAL, &timer, NULL);
    while(1) pause(); // 保持进程运行
    return 0;
}

(2),心跳包检测

#include <sys/timerfd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#define HEARTBEAT_INTERVAL 5

void send_heartbeat(int sockfd) {
    const char *msg = "HEARTBEAT";
    send(sockfd, msg, strlen(msg), 0);
}

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    // 连接服务器代码省略...
    
    int timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
    struct itimerspec its = {
        .it_value = {.tv_sec = HEARTBEAT_INTERVAL, .tv_nsec = 0},
        .it_interval = {.tv_sec = HEARTBEAT_INTERVAL, .tv_nsec = 0}
    };
    timerfd_settime(timer_fd, 0, &its, NULL);

    while(1) {
        uint64_t exp;
        read(timer_fd, &exp, sizeof(exp));
        send_heartbeat(sockfd); // 每5秒发送心跳包
    }
    close(timer_fd);
    return 0;
}

(3)timerfd+epoll实现高精度定时器采集传感器数据

#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>

#define SENSOR_PATH "/dev/temperature_sensor"  // 传感器设备路径
#define POLL_INTERVAL_MS 200                   // 采集间隔200ms

int read_sensor_data(int fd) {
    char buf[32];
    int ret = read(fd, buf, sizeof(buf));
    if(ret > 0) {
        printf("Sensor value: %.*s\n", ret, buf);
        return 0;
    }
    return -1;
}

int main() {
    // 打开传感器设备
    int sensor_fd = open(SENSOR_PATH, O_RDONLY | O_NONBLOCK);
    if(sensor_fd == -1) {
        perror("open sensor failed");
        return -1;
    }

    // 创建定时器
    int timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
    struct itimerspec its = {
        .it_interval = {.tv_sec = 0, .tv_nsec = POLL_INTERVAL_MS * 1000000},
        .it_value = {.tv_sec = 1, .tv_nsec = 0}  // 首次1秒后触发
    };
    timerfd_settime(timer_fd, 0, &its, NULL);

    // 创建epoll实例
    int epoll_fd = epoll_create1(0);
    struct epoll_event timer_ev = {
        .events = EPOLLIN,
        .data.fd = timer_fd
    };
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &timer_ev);

    // 事件循环
    while(1) {
        struct epoll_event events[2];
        int n = epoll_wait(epoll_fd, events, 2, -1);
        for(int i=0; i<n; i++) {
            if(events[i].data.fd == timer_fd) {
                uint64_t exp;
                read(timer_fd, &exp, sizeof(exp));
                read_sensor_data(sensor_fd);  // 定时读取传感器
            }
        }
    }

    close(timer_fd);
    close(sensor_fd);
    return 0;
}

 3,内核态使用

(1)精度内核定时器(hrtimer)‌ 适合需要微秒级精度的内核任任务

#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/io.h>

#define REG_ADDR 0xFE200000  // 设备寄存器物理地址
#define CHECK_INTERVAL_NS 200000000  // 200ms间隔

static struct hrtimer hr_timer;
static void __iomem *reg_map;

enum hrtimer_restart timer_callback(struct hrtimer *timer) {
    u32 reg_value = ioread32(reg_map);
    printk(KERN_INFO "Device reg value: 0x%x\n", reg_value);
    
    hrtimer_forward_now(timer, ns_to_ktime(CHECK_INTERVAL_NS));
    return HRTIMER_RESTART;
}

static int __init timer_init(void) {
    // 映射硬件寄存器
    reg_map = ioremap(REG_ADDR, sizeof(u32));
    if (!reg_map) {
        printk(KERN_ERR "Failed to map hardware register\n");
        return -ENOMEM;
    }

    // 初始化高精度定时器
    hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    hr_timer.function = &timer_callback;
    hrtimer_start(&hr_timer, ns_to_ktime(CHECK_INTERVAL_NS), HRTIMER_MODE_REL);
    
    printk(KERN_INFO "Hardware monitor module loaded\n");
    return 0;
}

static void __exit timer_exit(void) {
    hrtimer_cancel(&hr_timer);
    iounmap(reg_map);
    printk(KERN_INFO "Module unloaded\n");
}

module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("YourName");

(2)内核timer_list 使用举例

内核timer_list 基于jiffies时钟滴答使用检测看门狗举例

#include <linux/timer.h>
static struct timer_list wdt_timer;

void wdt_callback(struct timer_list *t) {
    if(!feed_dog()) {  // 检测喂狗信号
        panic("Watchdog timeout!");
    }
    mod_timer(&wdt_timer, jiffies + msecs_to_jiffies(500)); // 500ms周期检测
}

void init_watchdog(void) {
    timer_setup(&wdt_timer, wdt_callback, 0);
    mod_timer(&wdt_timer, jiffies + msecs_to_jiffies(500));
}

Linux内核中使用timer_stats统计定时器事件 


#include <linux/module.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>

static struct timer_list test_timer;
static unsigned long timeout_count;

void timer_callback(struct timer_list *t) {
    timeout_count++;
    mod_timer(&test_timer, jiffies + msecs_to_jiffies(100));
}

static int proc_show(struct seq_file *m, void *v) {
    seq_printf(m, "Timer stats:\n");
    seq_printf(m, "Expired count: %lu\n", timeout_count);
    seq_printf(m, "Current jiffies: %lu\n", jiffies);
    return 0;
}

static int proc_open(struct inode *inode, struct file *file) {
    return single_open(file, proc_show, NULL);
}

static const struct proc_ops proc_fops = {
    .proc_open = proc_open,
    .proc_read = seq_read,
    .proc_lseek = seq_lseek,
    .proc_release = single_release,
};

static int __init timer_init(void) {
    timer_setup(&test_timer, timer_callback, 0);
    mod_timer(&test_timer, jiffies + msecs_to_jiffies(100));
    proc_create("timer_stats", 0, NULL, &proc_fops);
    return 0;
}

static void __exit timer_exit(void) {
    del_timer_sync(&test_timer);
    remove_proc_entry("timer_stats", NULL);
}

module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开缓缓归以

你的鼓励将是我创作的最大动力,

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值