Linux字符设备驱动实现掷骰子功能无法读取设备数据问题求助
问题分析与解决方案
核心问题1:驱动read函数的偏移量判断逻辑错误
你在my_read中加了if(*ppos != 0) return 0;的逻辑,用户态第一次read之后,你把*ppos设成了sizeof(val)(通常int为4字节),第二次调用read时ppos已经不是0,直接返回0,不会再执行拷贝逻辑,所以测试时只会第一次读可能拿到数据,后续调用全返回空内容。
如果你希望每次调用read都返回新的骰子值,不需要记录偏移量,直接删掉
if(*ppos !=0) return 0;和*ppos = len;这两行即可。
核心问题2:数据类型不匹配
驱动里往用户空间拷贝的是int类型的二进制数值,不是ASCII字符串,测试代码用%s打印buf自然显示异常,甚至会因为缺少字符串结束符出现乱码。
修复方案
驱动端修改(dicedriver.c)
调整my_read函数逻辑:
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ val = get_random_byte(6)+1; int len = sizeof(val); if(count < len){ return -EINVAL; } if(copy_to_user(buf, &val, len)!=0){ printk(KERN_ALERT "ERROR while copying to buffer"); return -EINVAL; } return len; }
测试代码修改(testing.c)
用对应类型接收二进制值,调整打印逻辑:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> int main(){ int fd = 0, ret = 0; int i=0; int dice_val; // 用int类型匹配驱动返回的二进制数据 fd = open("/dev/dice_device", O_RDONLY); if(fd < 0) { perror("打开设备失败"); return 1; } printf("打开的设备文件描述符 :%d\n",fd); for(i=0;i<10;i++){ ret = read(fd, &dice_val, sizeof(dice_val)); if(ret < 0) { perror("读取设备失败"); break; } printf("第%d次掷骰子结果:%d, 读取字节数:%d\n", i+1, dice_val, ret); } close(fd); return 0; }
其他排查点
- 驱动加载后确认
/dev/dice_device的权限,普通用户默认没有读权限,可以执行sudo chmod 666 /dev/dice_device临时开放权限,或者用root身份运行测试程序。 - 如果还是出现copy_to_user报错,检查用户态传入的buf地址是否合法,上述修改已经直接传入int变量的地址,不会出现地址非法的问题。
内容的提问来源于stack exchange,提问作者nwlynx
相关产品推荐
相关产品推荐

