在驱动开发中,ioctl是很常用的应用层与内核通信的接口,今天调试过程中遇到一个ioctl调用不执行的问题,有点意思,写篇博客记录一下。
对于网络设备,内核通过宏SIOCDEVPRIVATE给各个设备预留了一组私有ioctl命令,驱动可以自行定义响应函数来执行相应的操作。今天接到一个需求,要在驱动里添加一个清空用户统计信息的功能,于是相应的就需要增加一个ioctl命令供应用层调用。看了驱动代码,已定义的私有ioctl命令从(SIOCDEVPRIVATE+0)一直到(SIOCDEVPRIVATE+16),于是理所当然的,我顺着添加了一条ioctl命令:
#define IEEE80211_IOCTL_CLEAR_STA_STATS (SIOCDEVPRIVATE+17)
应用层的调用代码如下:
int sockfd = 0;
struct iwreq iwr;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
ERROR("socket(SOCK_DRAGM)");
return ERROR;
}
memset(&iwr, 0, sizeof(iwr));
strncpy(iwr.ifr_ifrn.ifrn_name, vapName /* 网卡设备名 */, sizeof(iwr.ifr_ifrn.ifrn_name));
iwr.ifr_ifrn.ifrn_name[sizeof(iwr.ifr_ifrn.ifrn_name)-1] = '\0';
iwr.u.data.pointer = (void *)buf; /* station的MAC地址 */
iwr.u.data.length = sizeof(buf);
if (ioctl(sockfd, IEEE80211_IOCTL_CLEAR_STA_STATS, &iwr) < 0)
{
ERROR("Unable to clear station statistics");
return ERROR;
}
编译、烧录很顺利,但接下来发现这条ioctl调用没有生效,返回一直是-1。在驱动的ioctl函数里加打印信息,发现除了我加的命令没有打印输出,驱动自带的其他私有命令都有打印。也就是说我加的调用,根本没有进到驱动的ioctl函数。对比了应用层的调用代码,发现与其他命令并无区别,思考了一会,只能试着猜测是不是我加的命令参数超出了某个范围限制?
为了验证我的猜测,只能去内核源码中寻找答案。在内核源码目录中搜索SIOCDEVPRIVATE,终于在/net/core/dev_ioctl.c的dev_ioctl()函数中找到了如下代码:
switch (cmd) {
case XXXX:
XXXX;
case XXXX:
XXXX;
...
default:
if (cmd == SIOCWANDEV ||
cmd == SIOCGHWTSTAMP ||
(cmd >= SIOCDEVPRIVATE &&
cmd |