【发布时间】:2015-01-31 09:19:17
【问题描述】:
我正在尝试将 ioctl 接口添加到 Linux 内核 3.12 中的 CAN 驱动程序,这是一个网络设备。
我已经以这种方式向驱动程序添加了ioctl处理
#define C_CAN_SET_FILTERS _IOW('z', 3, void *)
static int c_can_ioctl(struct net_device *dev, struct ifreq *ifr, int arg)
{
switch (arg)
{
case C_CAN_SET_FILTERS:
netdev_err(dev, "CAN: ioctl C_CAN_SET_FILTERS called with arg %d\n", arg);
break;
default:
netdev_err(dev, "CAN: ioctl called with invalid cmd\n");
}
return 0;
}
static const struct net_device_ops c_can_netdev_ops = {
.ndo_open = c_can_open,
.ndo_stop = c_can_close,
.ndo_start_xmit = c_can_start_xmit,
.ndo_do_ioctl = c_can_ioctl,
};
dev->netdev_ops = &c_can_netdev_ops;
我添加了调试以确保上述代码在驱动程序加载时实际执行。
然后在用户空间我有这段代码...
#define C_CAN_SET_FILTERS _IOW('z', 3, void *)
if(ioctl(CANConfig[hndl].s, C_CAN_SET_FILTERS, &filterList) < 0) {
perror("C_CAN install filters failed");
}
我已经验证 CANConfig[hndl].s 是一个整数,它评估为进入 CAN 驱动程序(即 CAN0)的通道的打开文件描述符。事实上,代码中其他地方的这个 ioctl 调用确实有效
if(ioctl(CANConfig[hndl].s, SIOCGIFINDEX, &ifr) < 0)
响应始终是 ENOTTY AKA“设备不合适的 ioctl”
似乎自定义 ioctl 并未真正注册,因此内核在调用驱动程序中的自定义 ioctl 代码之前拒绝了用户空间 ioctl 调用。用于网络设备(如 SIOCGIFINDEX)的内置 ioctl 按预期工作。
谁能告诉我我在这里做错了什么?
我可以看到看起来有问题但显然不是的两件事是 (1) c_can_ioctl() 定义的第三个参数应该是一个无符号长整数,但它是一个整数。似乎网络设备ioctl接口不符合非网络设备的ioctl接口。并且 (2) net_device_ops 结构中有一个 .ndo_do_ioctl 插槽但没有 .ndo_do_unlocked_ioctl。
【问题讨论】:
-
你试过让 C_CAN_SET_FILTERS 等于 SIOCDEVPRIVATE + 1 吗?
标签: linux linux-kernel ioctl