如何修复 ioctl 请求阻止设备的“无效参数”

Posted

技术标签:

【中文标题】如何修复 ioctl 请求阻止设备的“无效参数”【英文标题】:how to fix 'invalid argument' for ioctl requests to block device 【发布时间】:2019-09-13 16:33:52 【问题描述】:

我正在编写一个小型 c 程序来制作磁带状态并通过

查找请求
        ioctl(int fd, long int request, &io_buf) 

但经过试验和大量错误后,ioctl 返回 -1 并显示错误消息“无效参数”

我在 Linux 上并以 sudo 运行我的程序。我要向其发出请求的设备是通过 SCSI 连接的光驱。我尝试了磁带状态并通过将请求(分别为MTIOCGETMTIOCTOP)传递给ioctl 来寻找请求。

磁带状态函数的代码 sn-p 其中 fd 是 open() 返回的设备的文件描述符,mtgetbuf 是来自 sys/mtio.h 的 mtget 结构的实例

       stat = ioctl(fd, MTIOCGET, &mtgetbuf);
       if (stat == -1)
       
          perror("error on ioctl MTIOCGET request: ")
          return EXIT_FAILURE;
       

寻找磁带功能的类似代码 sn-p 除了mtopbuf 是 mtop 结构的一个实例,MTSEEK 是为寻找操作定义的操作码,也在sys/mtio.h

        mtopbuf.mt_op = MTSEEK;
        stat = ioctl(fd, MTIOCTOP, &mtopbuf);
        if (stat == -1)
        
           perror("error on ioctl MTIOCGET request: ")
           return EXIT_FAILURE;
        

我希望从 ioctl 和各自的结构实例 mtgetbuf 和 mtopbuf 成功返回,而不是无效参数错误消息和返回 -1,以使其成员填充设备提供的数据。

即带有MTIOCGET 请求的成功ioctl() 命令将向mtgetbuf mt_type 成员返回MT_ISSCSI1MT_ISSCSI2MT_ISUNKNOWN 的值(我不相信它是任何其他定义的值)其他供应商特定的设备)。

注意:我知道 linux/mtio.h 头文件,我尝试将其包含在 sys/mtio.h 的位置,但结果是一样的。

【问题讨论】:

请务必man st并详细阅读。在致电 MTIOCGET 之前,您需要先致电 MTNOP。另外,发布您打开设备的代码,并包含您正在使用的来自/dev 的条目。 感谢@MikeAndrews。阅读st 的手册页,并尝试先调用MTNOP。实际上,我通过<scsi/sg.h> 使用 SCSI Generic Linux 驱动程序取得了一些成功。我可以通过ioctl(fd, SG_IO, &io_hdr) 发出成功的INQUIRY 命令,其中io_hdrsg_io_hdr_t 的一个实例,在<scsi/sg.h> 中找到。当我使用此策略或返回 linux/mtio.h 使用 seek 6 或 10 字节命令获得成功时,将发布代码更新 【参考方案1】:

我最近使用 SCSI 通用 Linux 驱动程序 (SG) 成功向块设备发出请求。三个头文件(如下)提供了操作码、用于从设备传递和检索数据的结构以及其他信息。

SCSI SG 头文件:

        /usr/include/scsi/scsi.h
        /usr/include/scsi/scsi_ioctl.h
        /usr/include/scsi/sg.h

在线资源的组合有助于理解如何打包、发送和接收请求:

1) TLDP SCSI Generic (sg) HOW-TO 指南是关于通过 SG 驱动程序与 SCSI 设备通信的信息字体。提供了指向它的链接here。它详细解释了可以发出的各种命令,如何通过创建 sg_io_hdr_t 结构的实例来打包命令,以及通过programming example 发送返回设备基本供应商信息的 SCSI INQUIRY 命令。还有用于错误处理和理解不成功的 SCSI 请求的状态和感知代码。

2) Seagate 的 SCSI 命令参考手册有时有助于了解 SCSI 命令中的字节/位结构。通常,操作码占用第一个字节,其余字节为零。本参考手册中的操作码是在上述三个头文件之间定义的。

我已经能够发送成功的 INQUIRY 和 GET_SG_VERSION_NUMBER 请求,并且很可能能够发送 SEEK(6)、READ_CAPACITY(10) 和 REZERO_UNIT 命令。我说很可能是因为没有返回 -1/errno 值,也没有将任何信息传递回指示警告/错误(SCSI、主机适配器或驱动程序状态代码)的感知缓冲区。

希望这能回答 OP 的问题。

【讨论】:

以上是关于如何修复 ioctl 请求阻止设备的“无效参数”的主要内容,如果未能解决你的问题,请参考以下文章

如何在 BigQuery UI 中安排查询时修复“请求包含无效参数”错误

`ioctl` 读写 GPIO:无效参数

python-daemon 阻止对 ctypes 链接的 C 用户库的 ioctl 调用

如何使用 Ajax Api 在 Google Distance Matrix API 中修复“跨源请求被阻止”[重复]

将cookie添加到chromedriver时如何修复Selenium中的“无效参数:无效'到期'”?

向 iOS 设备发送数据消息会导致 FirebaseMessagingException:请求包含无效参数