在某些情况下,我想安排一个适用于自定义数据的计时器(struct timer_list
)。此结构的function
字段包含将被触发的实际函数,定义如下:
void (*function)(unsigned long);
问题是我想传递指针而不是unsigned long
。我知道根据体系结构,int-ptr转换可能是安全的,也可能不安全,但是我无法找到所有架构是否将long
整数与指针对齐所以这是我的问题(实际上是两个 - in-one):
执行long
到void*
投射是否安全?如果不是,我应该如何处理unsigned long
参数以获取计时器函数中我想要的数据指针?
答案 0 :(得分:4)
如果是计时器功能,在某些其他情况下,可能只需将指向数据结构的指针转换为unsigned long
,将其存储在data
字段中struct timer_list
并将计时器函数的参数强制转换回指向数据结构的指针。这似乎是一种常见的做法。
Linux Driver Development, 3rd. ed.在第7章中就此问题陈述如下:
如果需要在参数中传递多个项目,可以将它们捆绑为单个数据结构,并将指针强制转换为unsigned long,这是所有支持的体系结构上的安全实践,在内存管理中非常常见(如本章所述) 15)。
内核中有很多例子,例如,参见ext4文件系统模块中的s_err_report
timer。指向struct super_block
的指针将传递给计时器函数,并转换为unsigned long
并返回,如上所述。
答案 1 :(得分:2)
您可以使用传递的数字作为包含自定义数据结构的数组的索引。
答案 2 :(得分:1)
完全使用Linux内核4.15 removed the data field,这里的答案已经过时了。根据我的推断,将参数传递给计时器回调的首选方法是将它们与计时器一起包含在结构中,并使用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的指针将传递给回调函数,而不是4.15之前版本中的unsigned long data
。
void callback(struct timer_list *t) {
struct timer_data *tmd = from_timer(tmd, t, timer);
datatype data = tmd -> data;
}