内核模块自动读取USB内容异常:仅获36字节设备名称求助
内核模块读取USB文件数据问题解决方案
- 你当前用URB只能拿到36字节设备描述符数据,是因为URB操作的是USB总线原始通信数据,而非文件系统层面的文件内容。内核层直接处理USB大容量存储的文件,必须走块设备+VFS文件系统的路径,而非直接读取URB。
核心解决步骤:
过滤USB大容量存储设备
在USB插入事件的notifier回调中,通过usb_interface结构体判断设备类型:struct usb_interface *intf = to_usb_interface(dev); if (intf->cur_altsetting->desc.bInterfaceClass != 0x08) { // 不是大容量存储设备,直接返回 return NOTIFY_DONE; }0x08是USB大容量存储设备的接口类标识,只有这类设备才需要后续处理。
获取块设备节点并挂载文件系统
USB大容量存储设备会被识别为块设备(如/dev/sdb),其分区(如/dev/sdb1)需要挂载到内核可访问的路径:struct vfsmount *mnt; struct path path; int ret; // 挂载分区,以vfat为例,需根据实际文件系统调整 mnt = vfs_kern_mount(&fat_fs_type, 0, "/dev/sdb1", NULL); if (IS_ERR(mnt)) { pr_err("Mount failed\n"); return PTR_ERR(mnt); } path.mnt = mnt; path.dentry = mnt->mnt_root;注意:需提前导入对应文件系统的驱动(如
CONFIG_FAT_FS),且内核版本不同,vfs_kern_mount的参数可能有差异,需适配Ubuntu 23.10的内核版本。通过VFS接口读取文件
挂载完成后,使用内核VFS接口操作文件,这才是获取实际文件数据的正确方式:struct file *file; char buf[4096]; loff_t pos = 0; ssize_t read_len; file = filp_open("/mnt/usb/test.txt", O_RDONLY, 0); if (IS_ERR(file)) { pr_err("Open file failed\n"); goto unmount; } // 切换地址空间,避免内核/用户空间访问冲突 mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); read_len = vfs_read(file, buf, sizeof(buf), &pos); if (read_len > 0) { pr_info("Read %zd bytes: %s\n", read_len, buf); // 这里可以添加文件复制逻辑 } set_fs(old_fs); filp_close(file, NULL);
unmount:
vfs_kern_unmount(mnt, 0);
### 关键注意事项 - 内核层操作VFS必须严格管理资源,所有打开的文件、挂载点都要正确释放,否则会导致内存泄漏或系统崩溃。 - Ubuntu 23.10内核版本较高,部分旧API已废弃,需参考对应内核版本的官方文档调整代码。 - 该操作仅适合学习实验,生产环境绝对禁止在内核层处理文件复制逻辑。 内容的提问来源于stack exchange,提问作者W. N
相关产品推荐
相关产品推荐

