使用CDROMREADMODE1 ioctl读取CD-ROM时出现EIO错误求助
CDROMREADMODE1调用返回EIO错误的排查方案
我正在开发一款支持底层CD接口的应用,读取TOC(目录表)操作正常,目标是一张可正常挂载浏览的Mode 1数据CD,轨道1起始于MSF 0:2:0。调用CDROMREADMODE1时始终返回-1,errno为EIO,但CDROMREADRAW可成功执行,怀疑是USB光驱不支持该命令。以下是具体排查和解决方向:
- 完整初始化
cdrom_msf结构
部分内核实现要求完整填充cdrom_msf的所有字段,避免未初始化的垃圾值导致内核解析错误。尝试初始化整个结构并设置起始/结束扇区为同一位置(读取单个扇区):
union { struct cdrom_msf msf; unsigned char buffer[CD_FRAMESIZE]; // 2048 bytes } arg; // 先清空整个结构 memset(&arg.msf, 0, sizeof(struct cdrom_msf)); // 设置起始MSF arg.msf.cdmsf_min0 = 0; arg.msf.cdmsf_sec0 = 2; arg.msf.cdmsf_frame0 = 0; // 设置结束MSF为同一位置,读取单个扇区 arg.msf.cdmsf_min1 = 0; arg.msf.cdmsf_sec1 = 2; arg.msf.cdmsf_frame1 = 0; int result = ioctl(cd_handle, CDROMREADMODE1, &arg);
检查设备权限与挂载状态
底层ioctl调用可能需要root权限,尝试以管理员身份运行程序。另外,CD挂载后内核可能独占设备,阻止底层读取操作,先卸载挂载点(umount /media/[username]/[cd label])后再执行读取命令。验证MSF地址的准确性
确认轨道1的起始MSF是否确实为0:2:0,可通过cdrecord -msinfo或cd-info工具交叉验证。若TOC查询返回的是LBA地址,需确保转换为MSF时没有计算错误(LBA转MSF公式:总帧数= LBA+150,分钟=总帧数//4500,秒=(总帧数%4500)//75,帧=总帧数%75)。兼容性替代方案
部分USB光驱对CDROMREADMODE1的支持存在兼容性问题,可改用CDROMREADRAW读取完整的2352字节扇区,自行提取Mode1的用户数据:Mode1扇区中,从第16字节开始的连续2048字节即为用户数据。查看内核日志定位细节
执行失败后,查看dmesg或/var/log/kern.log,内核通常会记录光驱返回的硬件错误细节,帮助进一步定位问题。
内容的提问来源于stack exchange,提问作者Hazel Stagner
相关产品推荐
相关产品推荐

