3

在某些情况下,我想安排一个struct timer_list处理自定义数据的计时器 ()。该function结构的字段保存将要触发的实际功能,定义如下:

void (*function)(unsigned long);

问题是我想传递一个指针而不是unsigned long. 我知道根据架构,int-ptr 转换可能安全也可能不安全,但我找不到所有架构是否都将long整数与指针对齐,所以这是我的问题(实际上是二合一):

执行 a longto void*cast 是否安全?如果不是,我应该如何处理unsigned long参数以在计时器函数中获取我想要的数据指针?

4

3 回答 3

8

Linux 内核 4.15完全删除了数据字段,使得这里的答案已经过时。根据我的推断,将参数传递给计时器回调的首选方法是将它们与计时器一起包含在一个结构中,并使用from_timer宏来检索它们,其定义为

#define from_timer(var, callback_timer, timer_fieldname) \
    container_of(callback_timer, typeof(*var), timer_fieldname) 

所以为了传递参数,定义一个额外的结构为

struct timer_data {
    struct timer_list timer;
    datatype data;
};

并将其传递给设置函数

struct timer_data *tmd = init_timer_data(); //your logic for init
timer_setup(&tmd->timer, callback, flags);

稍后,使用from_timer检索参数。默认情况下,指向 timer_list 的指针被传递给回调函数,而不是unsigned long data4.15 之前的版本。

void callback(struct timer_list *t) {
    struct timer_data *tmd = from_timer(tmd, t, timer);
    datatype data = tmd -> data;
}
于 2018-05-02T19:46:33.063 回答
5

在计时器函数和其他一些情况下,可以将指向数据结构的指针转换为unsigned long,将其存储在data字段中struct timer_list并将计时器函数的参数转换回指向数据结构的指针。这似乎是一种常见的做法。

Linux 驱动程序开发,第 3 期。编。在第 7 章中就该事项陈述如下:

如果您需要在参数中传递多个项目,您可以将它们捆绑为一个数据结构并将指针转换为 unsigned long,这是所有支持的架构上的安全做法,并且在内存管理中非常常见(如第 15 章所述)。

内核中有很多这样的例子,例如,参见ext4 文件系统模块中的s_err_report计时器。一个指向的指针struct super_block被传递给定时器函数,unsigned long如上面描述的那样。

于 2013-02-19T15:15:28.820 回答
2

您可以使用传递的数字作为包含自定义数据结构的数组的索引。

于 2013-02-19T09:23:34.330 回答