copy_to_user异常问题,发现按键值从驱动程序传输到测试程序时,两端数据不一致
驱动程序中按键保存值类型为int型,测试程序也是int,但是测试程序与驱动程序中的值不一致,以下是错误测试结果;
button_press:0 0 1 0 0 0//内核区传输前的按键值 copy to user succe key[0]=0x0 //测试程序接收到的按键值 key[1]=0x40010000 key[2]=0x0 key[3]=0xbebf5e90 key[4]=0x4000b614 key[5]=0xbebf5ed4
button_press[2] = 1 wake_up_interruptible q_buttons button_press:0 0 1 0 0 0 copy to user succe key[0]=0x0 key[1]=0x40010000 key[2]=0x0 key[3]=0xbebf5e90 key[4]=0x4000b614 key[5]=0xbebf5ed4
button_press[4] = 1 wake_up_interruptible q_buttons button_press:0 0 0 0 1 0 copy to user succe key[0]=0x0 key[1]=0x40010000 key[2]=0x0 key[3]=0xbebf5e90 key[4]=0x4000b614 key[5]=0xbebf5ed4 驱动程序中异常按键值读取函数
@Override static ssize_t button_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { ssize_t ret = 0; size_t size = min(count,sizeof(button_press)); /* 等待队列唤醒 */ wait_event_interruptible(q_buttons,isKey_Pressed); isKey_Pressed = 0; printk(">>>button_press:%d\t%d\t%d\t%d\t%d\t%d\n",button_press[0],button_press[1],button_press[2],button_press[3],button_press[4],button_press[5]); if(copy_to_user((void*)buffer,(const void*)&button_press,size)) { ret = -1; printk("copy to user failure\n"); } else { printk("copy to user succe\n"); memset((void*)&button_press,0,sizeof(button_press)); ret = size; } return ret; }将if(copy_to_user((void*)buffer,(const void*)&button_press,size))改为if(copy_to_user((void*)buffer,(const void*)&button_press,size*4))后,测试函数接收到数据就正常,正常的测试结果 button_press:0 0 0 0 1 0 copy to user succe key[0]=0x0 key[1]=0x0 key[2]=0x0 key[3]=0x0 key[4]=0x1 key[5]=0x0
button_press[3] = 1 wake_up_interruptible q_buttons button_press:0 0 0 1 0 0 copy to user succe key[0]=0x0 key[1]=0x0 key[2]=0x0 key[3]=0x1 key[4]=0x0 key[5]=0x0
button_press[5] = 1 wake_up_interruptible q_buttons button_press:0 0 0 0 0 1 copy to user succe key[0]=0x0 key[1]=0x0 key[2]=0x0 key[3]=0x0 key[4]=0x0 key[5]=0x1
总结,copy_to_user和copy_from_user,操作的数组类型应该默认为字符型,也就是说虽然驱动程序和测试程序都是int,但是copy_to_user仍然以字符型的数据长度传输复制,以该例为例,我们计划从驱动程序传输6个int的数据到测试程序区,实际只传输6个char的长度;
1.根据数据类型,修改实际要传输长度,如上我们要传输的是int,就可以在长度上乘以4,当然其他更好的方式最好; 2.如果只是保存按键值,也可以将驱动中按键值保存类型改为char,也可以避免这个问题。 该例测试源码,内核版本2.6.22.6 链接:https://pan.baidu.com/s/1yBF2i1ttPGmsjmN2pn1IPA 提取码:m2aq