如何在 linux 上的驱动程序中执行回调函数?
How can a callback function be executed within a driver on linux?
我必须修改在 linux 上运行的驱动程序以添加从外部应用程序调用的回调函数。代码我已经实现了,但是在电脑启动的时候执行,系统报错,卡死了。
这是我在驱动端的新代码:
typedef void (*callbackFunctionNoParams) ();
typedef struct T_EXI_CONFIGURE_BUS_
{
T_mode mode;
unsigned short NumeroRT;
T_SA_Enable SA_Enable;
unsigned short MINOR_CYCLE;
callbackFunctionNoParams callback;
} T_EXI_CONFIGURE_BUS;
typedef struct PciExiDev_
{
/**
* It represents a char device to read/write
*/
struct cdev charDevice;
/**
* IRQ assigned
*/
unsigned int irq;
/**
* Callback function to be invoked
*/
callbackFunctionNoParams callback;
/**
* Device control block
*/
EXI_DCB theDCB;
} PciExiDev;
驱动端执行代码:
static long exi_ioctl( struct file * filep, unsigned int cmd, unsigned long arg )
{
PciExiDev * aPciExiDev = (PciExiDev *) filep->private_data;
int result = SUCCESS;
int i, j;
long ret = 0;
//printk("Ioctl received %d.\n",cmd);
switch( cmd )
{
case FIO_EXI_CONFIGURE_BUS:
{
T_EXI_CONFIGURE_BUS config;
T_LISTA_TRANS *auxTrans1, *auxTrans2;
T_TRANSACTION_DCB *transDCB1;
T_OPI opi;
T_EXIS exis;
unsigned short dato;
unsigned short datolong[2];
unsigned short ControlBlock[12];
// printk("Exi configure bus initiated.\n");
printk("TNB. Exi ioctl CONFIGURE BUS.\n");
copy_from_user( &config, (T_EXI_CONFIGURE_BUS *) arg, sizeof(T_EXI_CONFIGURE_BUS) );
LeerDatos( &aPciExiDev->theDCB, OPI_ADDRESS, 1, (unsigned short *) &opi, 1 );
aPciExiDev->callback = config.callback;
aPciExiDev->theDCB.modo = config.mode;
aPciExiDev->theDCB.CicloMenor = config.MINOR_CYCLE;
(*aPciExiDev->callback)();
...
客户端的新代码:
if( theHWConfiguration.existExi() )
{
T_EXI_CONFIGURE_BUS bus_config;
// Configura la tarjega exi en modo Bus Controller.
bus_config.mode = BC;
bus_config.NumeroRT = 28;
bus_config.MINOR_CYCLE = 20;
bus_config.callback = &bcInterruptHandler2;
status = ioctl( A_fd_exi, FIO_EXI_CONFIGURE_BUS, reinterpret_cast<long>( &bus_config ) );
}
return status;
}
void C_EXI::bcInterruptHandler2()
{
std::cout<< "bcInterruptHandler2" << endl;
}
这是执行代码的结果:
Crash Image
如果有人可以帮助我或提出替代方法,我将不胜感激。
崩溃图像表明您的代码中某处有一个您试图访问的无效指针。恐怕我不能用提供的小上下文调试你的代码,但我可以给你一些建议:
- 在绝对必要之前尽量避免转换。
- 当您转换为指针时,请仔细检查这正是您需要做的。
- 报错信息中还有调用栈,看一下,找出错误所在。
- 您可以简单地在代码中添加一些 printk("%p", pointer) 来调试变量的内容。
您的 callback
在内核 space 绑定到 运行,然后您将其写入 std::cout
。在检查您的代码时,它表明内核模式地址 space 和用户端进程地址 space 之间存在冲突。这意味着如果 callback
函数在用户端声明,但在内核 space 中调用,则会出错。
我必须修改在 linux 上运行的驱动程序以添加从外部应用程序调用的回调函数。代码我已经实现了,但是在电脑启动的时候执行,系统报错,卡死了。
这是我在驱动端的新代码:
typedef void (*callbackFunctionNoParams) ();
typedef struct T_EXI_CONFIGURE_BUS_
{
T_mode mode;
unsigned short NumeroRT;
T_SA_Enable SA_Enable;
unsigned short MINOR_CYCLE;
callbackFunctionNoParams callback;
} T_EXI_CONFIGURE_BUS;
typedef struct PciExiDev_
{
/**
* It represents a char device to read/write
*/
struct cdev charDevice;
/**
* IRQ assigned
*/
unsigned int irq;
/**
* Callback function to be invoked
*/
callbackFunctionNoParams callback;
/**
* Device control block
*/
EXI_DCB theDCB;
} PciExiDev;
驱动端执行代码:
static long exi_ioctl( struct file * filep, unsigned int cmd, unsigned long arg )
{
PciExiDev * aPciExiDev = (PciExiDev *) filep->private_data;
int result = SUCCESS;
int i, j;
long ret = 0;
//printk("Ioctl received %d.\n",cmd);
switch( cmd )
{
case FIO_EXI_CONFIGURE_BUS:
{
T_EXI_CONFIGURE_BUS config;
T_LISTA_TRANS *auxTrans1, *auxTrans2;
T_TRANSACTION_DCB *transDCB1;
T_OPI opi;
T_EXIS exis;
unsigned short dato;
unsigned short datolong[2];
unsigned short ControlBlock[12];
// printk("Exi configure bus initiated.\n");
printk("TNB. Exi ioctl CONFIGURE BUS.\n");
copy_from_user( &config, (T_EXI_CONFIGURE_BUS *) arg, sizeof(T_EXI_CONFIGURE_BUS) );
LeerDatos( &aPciExiDev->theDCB, OPI_ADDRESS, 1, (unsigned short *) &opi, 1 );
aPciExiDev->callback = config.callback;
aPciExiDev->theDCB.modo = config.mode;
aPciExiDev->theDCB.CicloMenor = config.MINOR_CYCLE;
(*aPciExiDev->callback)();
...
客户端的新代码:
if( theHWConfiguration.existExi() )
{
T_EXI_CONFIGURE_BUS bus_config;
// Configura la tarjega exi en modo Bus Controller.
bus_config.mode = BC;
bus_config.NumeroRT = 28;
bus_config.MINOR_CYCLE = 20;
bus_config.callback = &bcInterruptHandler2;
status = ioctl( A_fd_exi, FIO_EXI_CONFIGURE_BUS, reinterpret_cast<long>( &bus_config ) );
}
return status;
}
void C_EXI::bcInterruptHandler2()
{
std::cout<< "bcInterruptHandler2" << endl;
}
这是执行代码的结果:
Crash Image
如果有人可以帮助我或提出替代方法,我将不胜感激。
崩溃图像表明您的代码中某处有一个您试图访问的无效指针。恐怕我不能用提供的小上下文调试你的代码,但我可以给你一些建议:
- 在绝对必要之前尽量避免转换。
- 当您转换为指针时,请仔细检查这正是您需要做的。
- 报错信息中还有调用栈,看一下,找出错误所在。
- 您可以简单地在代码中添加一些 printk("%p", pointer) 来调试变量的内容。
您的 callback
在内核 space 绑定到 运行,然后您将其写入 std::cout
。在检查您的代码时,它表明内核模式地址 space 和用户端进程地址 space 之间存在冲突。这意味着如果 callback
函数在用户端声明,但在内核 space 中调用,则会出错。