内核定时执行需参函数

linux内核中的timer_setup(timer, callback, flags)函数,现在变成了回调函数,我不会用这个。请问如何在内核驱动中使用定时器执行一个需要参数的函数呢?

  • 在新版本的内核中,使用timer_setup函数注册定时器时,需要将定时器的回调函数改为void (*)(struct timer_list *), 即回调函数的参数必须是struct timer_list类型的指针。

  • 如果需要在回调函数中传递其他参数,可以通过定时器的data成员传递。例如,可以将需要传递的参数设置为一个结构体,然后将结构体的指针赋值给定时器的data成员。在回调函数中,可以通过timer_list结构体的data成员获取参数的指针。

  • 以下是一个示例代码,用于在内核驱动中使用定时器执行一个需要参数的函数:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>

struct my_data {
    int arg1;
    char arg2;
};

static void my_timer_callback(struct timer_list *timer)
{
    struct my_data *data = (struct my_data *)timer->data;
    // 使用data指向的结构体中的参数执行操作
    printk(KERN_INFO "my_timer_callback: arg1=%d, arg2=%c\n",
           data->arg1, data->arg2);
}

static struct timer_list my_timer;

static int __init my_init(void)
{
    struct my_data *data = kmalloc(sizeof(struct my_data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    // 设置定时器回调函数和参数
    data->arg1 = 123;
    data->arg2 = 'a';
    my_timer.data = data;
    my_timer.function = my_timer_callback;
    my_timer.expires = jiffies + msecs_to_jiffies(1000);

    // 启动定时器
    add_timer(&my_timer);
    return 0;
}

static void __exit my_exit(void)
{
    // 删除定时器并释放参数内存
    del_timer(&my_timer);
    kfree(my_timer.data);
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
  • 在这个示例中,使用kmalloc动态分配了一个my_data结构体,将需要传递的参数存储在结构体中。然后,将结构体的指针赋值给定时器的data成员,在回调函数中通过timer_list结构体的data成员获取参数的指针,并执行操作。最后,在模块卸载时删除定时器并释放参数内存。

小魔女参考了bing和GPT部分内容调写:
Linux内核中可以使用setup_timer()函数来设置一个定时器,该函数接受一个回调函数作为参数,该回调函数可以接受参数。因此,我们可以创建一个函数,该函数接受我们需要的参数,然后将其作为回调函数传递给setup_timer()函数。

例如:

void my_timer_callback(unsigned long data)
{
    // do something with data
}

void setup_my_timer(unsigned long data)
{
    setup_timer(&my_timer, my_timer_callback, data);
    mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
}

上面的代码中,我们定义了一个my_timer_callback()函数,该函数接受一个参数data,然后我们定义了一个setup_my_timer()函数,该函数接受一个参数data,然后将其传递给setup_timer()函数,以便在定时器到期时调用my_timer_callback()函数。
回答不易,记得采纳呀。

参考GPT和自己的思路,在 Linux 内核中,你可以使用 struct timer_list 结构体来实现定时器。这个结构体包含了一个回调函数 void (*)(struct timer_list *),以及一个私有数据指针 void *data。

以下是一个使用定时器调用需要参数的函数的示例代码:

#include <linux/timer.h>

static void my_timer_callback(struct timer_list *t)
{
    void (*my_func)(void *data);
    void *my_data;

    my_func = t->function; // 获取需要调用的函数指针
    my_data = t->data;     // 获取需要传递的数据指针

    // 调用需要参数的函数
    my_func(my_data);

    // 重新设置定时器
    mod_timer(t, jiffies + msecs_to_jiffies(1000));
}

static void my_function(void *data)
{
    int my_parameter = *((int *)data);
    // 进行需要执行的操作
}

int my_init(void)
{
    struct timer_list my_timer;
    int my_parameter = 123;

    // 初始化定时器
    timer_setup(&my_timer, my_timer_callback, 0);
    my_timer.data = &my_parameter; // 传递需要的参数
    my_timer.expires = jiffies + msecs_to_jiffies(1000);

    // 启动定时器
    add_timer(&my_timer);

    return 0;
}

void my_exit(void)
{
    // 删除定时器
    del_timer_sync(&my_timer);
}

module_init(my_init);
module_exit(my_exit);

在内核驱动中使用定时器执行一个需要参数的函数,可以通过在回调函数中调用一个函数指针来实现。

首先,定义一个包含需要传递的参数的结构体:

struct my_data {
    int val1;
    char *val2;
};

然后,在驱动初始化函数中创建定时器,并将结构体和函数指针作为参数传递到回调函数中:

struct my_data data;
data.val1 = 123;
data.val2 = "hello";

struct timer_list my_timer;
my_timer.function = my_timer_callback;
my_timer.data = (unsigned long)&data;
my_timer.expires = jiffies + HZ; // 定时器过期时间
add_timer(&my_timer);

在回调函数中,将参数结构体转换成正确的类型,并执行需要传递参数的函数:

void my_timer_callback(unsigned long data)
{
    struct my_data *my_data = (struct my_data*)data;
    my_function(my_data->val1, my_data->val2);
}

其中,my_function为需要传递参数的函数。注意,由于定时器回调函数是在中断上下文中执行的,因此需要注意不要在其中执行可能休眠的操作。

  • 这篇博客: Linux内核定时器---init_timer()、add_timer()与mod_timer()使用中的 二、内核定时器使用方法 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • struct timer_list timer; /* 定义定时器 */
    
    /* 定时器回调函数 */
    void function(unsigned long arg)
    {
    /*
    * 定时器处理代码
    */
    
    /* 如果需要定时器周期性运行的话就使用 mod_timer
    * 函数重新设置超时值并且启动定时器。
    */
    mod_timer(&dev->timertest, jiffies + msecs_to_jiffies(2000));
    }
    
    /* 初始化函数 */
    void init(void)
    {
    init_timer(&timer); /* 初始化定时器 */
    
    timer.function = function; /* 设置定时处理函数 */
    timer.expires=jffies + msecs_to_jiffies(2000);/* 超时时间 2 秒 */
    timer.data = (unsigned long)&dev; /* 将设备结构体作为参数 */
    
    /*上面也可以用setup_timer()函数*/
    
    add_timer(&timer); /* 启动定时器 */
    }
    
    /* 退出函数 */
    void exit(void)
    {
    del_timer(&timer); /* 删除定时器 */
    /* 或者使用 */
    del_timer_sync(&timer);
    }
    

    此处参考《【正点原子】I.MX6U嵌入式Linux驱动开发指南》