应用程序通过iotcl往驱动传参数,居然收到是错的。。。。。
本帖最后由 zheguzai 于 2012-05-04 17:46 编辑今天遇到这个问题,简直让我很吐血,搞了好久还是不行,因为感觉这个根本就不会出问题的,可是居然出了这种问题
以前的驱动要添加接口,所以我就在原来驱动的ioctl中添加了一项,并且通过应用程序调用该ioctl,可是奇怪的事情发生了,我传递给
驱动的数据,居然不是我想要的,搞了半天都不行,期间试了两种方法,第一种:驱动中不用copy_from_user()函数来接收从应用传来的指针,可是这样也不行,第二种,就是用copy_from_user()函数来接受从应用传来的指针,可是还是不行。不说了上代码,大家帮我看看,哪里出问题了。。。。
应用层代码,调用的代码很简单就两句。。。。我从应用传过去的数据就是1和2,其他的数据都会报错的。
int channel= 2;
if (ioctl(inputFd, VPFE_CMD_SELECT_TVP5158_CHANNEL, &channel) == -1)
{
printf("VPFE_CMD_SELECT_TVP5158_CHANNEL failed\n");
}驱动代码: case VPFE_CMD_SELECT_TVP5158_CHANNEL:
{
intchannel_id;
copy_from_user(&channel_id, (int *)arg, sizeof(int));
printk("channel_id = %d\n",channel_id);//本来这句打印出来应该是2的,可是它不是,是个垃圾数值,
if (channel_id < 1 || channel_id > 2)
{
ret = -EINVAL;
break;
}
tvp5158_ctrl(TVP5158_SELECT_CHANNEL, &channel_id);
break;
}
驱动中刚开始用这种方式实现的。一样是不行的 case VPFE_CMD_SELECT_TVP5158_CHANNEL:
{
int*channel_id = (int *)arg;
printk("channel_id = %d\n",*channel_id);//本来这句打印出来应该是2的,可是它不是,是个垃圾数值,
if (*channel_id < 1 || *channel_id > 2)
{
ret = -EINVAL;
break;
}
tvp5158_ctrl(TVP5158_SELECT_CHANNEL, channel_id);
break;
} 大家帮我看看,看是哪里出错了,谢谢了 。。。。。。。。。。 本帖最后由 xxw19840406 于 2012-05-04 18:04 编辑
void __user *arg = (void __user *)arg;
驱动中arg有没有这个
然后copy_from_user(&channel_id, (int *)arg, sizeof(int));
改成 copy_from_user(&channel_id, arg, sizeof(int));
代码贴全点 xxw19840406 发表于 2012-05-04 18:03 static/image/common/back.gif
void __user *arg = (void __user *)arg;
驱动中arg有没有这个
驱动里面没有你说的void __user *arg = (void __user *)arg; 这句的。 不应该用copy_from_user的:wink: zheguzai 发表于 2012-05-04 19:35 static/image/common/back.gif
驱动里面没有你说的void __user *arg = (void __user *)arg; 这句的。
这个不一定是真正的原因
一般copy_from_user都是要检查返回的,LZ可以看看是否出错 xxw19840406 发表于 2012-05-07 09:40 static/image/common/back.gif
这个不一定是真正的原因
一般copy_from_user都是要检查返回的,LZ可以看看是否出错
查过了,返回值就是错误的。。。。 ldd3 中的做法是:因为ioctl 通常涉及到小的数据,所以先用access_ok()验证用户空间地址有效性,
然后使用不做类型检查的快速的函数:put_user(), __put_user(), get_user,__get_user().
你把代码改成这样试试。 case VPFE_CMD_SELECT_TVP5158_CHANNEL:
{
intchannel_id;
int err = access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
if(!err) return -EFAULT;
__get_user(channel_id, (int __user *)arg);
printk("channel_id = %d\n",channel_id);//本来这句打印出来应该是2的,可是它不是,是个垃圾数值,
if (channel_id < 1 || channel_id > 2)
{
ret = -EINVAL;
break;
}
tvp5158_ctrl(TVP5158_SELECT_CHANNEL, &channel_id);
break;
} 友情提醒:你检查一下你的ioctl的原型和你的ioctl函数的实现,看看两者的参数个数是不是一致。 做个记号,下次好找! 非常感谢大家的回帖,那个davinci VPFE驱动里对IOCTL又进行了一次封装,本来我们只写一个ioctl函数的,它又写了一个调用真正的ioctl,并且对参数进行了处理。。。所以我的那个参数传进去之后就不对了。。。
页:
[1]