从旧的init_timer适应新的timer_setup

El *_*ldo 2 c linux linux-device-driver linux-kernel

我一直试图在没有原始主板制造商支持的情况下将驱动程序从2.6移植到4.n(并且Linux经验非常有限).

原始驱动程序使用init_timer()并传入指向timer_list结构的指针.该limer_list结构的'data'元素被设置为指向另一个内存结构的指针,并且'function'元素被设置为回调.在回调函数内部,'data'元素用于访问其他东西.

当前的timer init方法使用timer_setup(timer_list*,callback,(unsigned int)flags); 并且timer_list结构已更改为消除'data'字段.

我不确定通知等效'data'元素的回调函数的最佳/正确方法是什么.谁能提供一些指导?

这是老司机的片段......

myDevice * dev;

dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);    
init_timer(dev->getIntrTimer);

dev->getIntrTimer->data = (unsigned long) dev;
dev->getIntrTimer->function = GetIntrTimerCallback;
Run Code Online (Sandbox Code Playgroud)

回调函数如下所示:

void GetIntrTimerCallback(unsigned long devAddr)
{
    myDevice *dev = (myDevice *) devAddr;
    dev->blahBlah++; // etc.
Run Code Online (Sandbox Code Playgroud)

因此,旧代码将指针传递给myDevice,因此在回调中可以访问该结构.

但是使用新的计时器方法只有一个4字节的int,但指针是8(或其他).

我想做的是:

dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
timer_setup(dev->getIntrTimer, GetIntrTimerCallback, dev);
Run Code Online (Sandbox Code Playgroud)

但是当然会产生编译错误,因为dev是一个指向myDevice类型的指针,它不适合int.

我想念傻事,不是吗?

red*_*0ct 8

timer_setup()自4.14 Linux内核(FYI有一个与三个参数存在setup_timer()略微更早版本).如果您维护一些与最新内核相关的代码 - 每次API更改时都必须以适当的方式更改它.现在您可以通过from_timer()基于的特殊功能访问您的数据container_of().

timer_list 通常不用作struct中的指针,因此该示例意味着正常使用,可能类似于:

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
    init_timer(&dev->getIntrTimer);
    dev->getIntrTimer.data = (unsigned long) dev;
    dev->getIntrTimer.function = GetIntrTimerCallback;
    /* ... */
    add_timer(&dev->getIntrTimer);
#else
    timer_setup(&dev->getIntrTimer, GetIntrTimerCallback, 0);
    /* the third argument may include TIMER_* flags */
    /* ... */
#endif
Run Code Online (Sandbox Code Playgroud)

回调函数:

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
void GetIntrTimerCallback(unsigned long devAddr)
{
    myDevice *dev = (myDevice *) devAddr;
#else
void GetIntrTimerCallback(struct timer_list *t)
{
    myDevice *dev = from_timer(dev, t, getIntrTimer);
#endif
    /* Do something with "dev" */
Run Code Online (Sandbox Code Playgroud)

阅读:

  • @ElRonaldo如果在您的struct中将`timer_list`声明为指针,那么关于`container_of()`的错误消息是非常合理的.如上所述,示例***不适用于案例***`typedef struct {struct timer_list*getIntrTimer;/*smth else*/} myDevice;`,但***用于大小写***`typedef struct {struct timer_list getIntrTimer;/*smth else*/} myDevice;` (2认同)