You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:09:01