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

Python调用ioctl报FileNotFoundError但C代码同参数可正常运行

Python调用ioctl返回FileNotFoundError但设备文件实际存在的问题

我正在为一款通过ioctl通信的设备开发Python驱动,参考厂商提供的C示例代码,但卡在客户端连接调用上。Python中调用ioctl时返回FileNotFoundError: [Errno 2] No such file or directory,但该文件实际存在且我有访问权限(同款逻辑的C代码可正常运行)。

已做的尝试:

  • 使用无效文件描述符(比如1/2)会出现其他错误,说明程序能识别文件描述符,但仍提示文件不存在
  • 试过用os.fdopen将io.File对象传入fcntl.ioctl,结果一致
  • 从C代码中打印出request整数和返回结构体的大小,确保Python与C的ioctl调用参数完全一致
  • 确认文件描述符已正常打开且活跃(通过lsof验证)

C代码及输出

//c code
int pse_client_connect(void) {
    int fd, ret;
    struct ishtp_cc_data cc_data;

    // Prep input connection data
    memcpy(&(cc_data.in_client_uuid), &pse_smhi_guid, sizeof(pse_smhi_guid));

    // Open the pse character device for operations
    fd = open(PSE_CHRDEV, O_RDWR);
    printf("File Descriptor: %i\n", fd);
    printf("Size of Struct: %li\n",sizeof(cc_data));
    printf("Request Int: %li\n", IOCTL_ISHTP_CONNECT_CLIENT);
    if (fd <= 0) {
        printf("Failed to open the pse device file\nAre you running as root?\n");
        return fd;
    }

    // Send the connection IOCTL
    ret = ioctl(fd, IOCTL_ISHTP_CONNECT_CLIENT, &cc_data);
    if (ret) {
        printf("Failed to connect to the PSE over ISHTP/HECI\n");
        return ret;
    }

    return fd;
}

输出:

File Descriptor: 3
Size of Struct: 16
Request Int: 3222292481

Python代码及输出

#Python Code
import fcntl, array, os

def pse_client_connect():
    device_file=os.open("/dev/pse", os.O_RDWR)
    print(device_file)
    if (device_file <= 0):
        print("Failed to open the pse device file\nAre you running as root?\n")
    buf = array.array('B', [0]*16)
    ret = fcntl.ioctl(device_file,3222292481,buf,True )
    print(buf)
    os.close(device_file)

if __name__ == "__main__":
    pse_client_connect()

输出:

(base) root@host:/# python main.py
3
Traceback (most recent call last):
  File "/home/tech/Downloads/pse_heci/py_example/main.py", line 14, in <module>
    pse_client_connect()
  File "/home/tech/Downloads/pse_heci/py_example/main.py", line 9, in pse_client_connect
    ret = fcntl.ioctl(device_file,3222292481,buf,True )
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory

文件描述符验证

(base) root@host:/# sudo lsof | grep "/dev/pse"
python    311743                              root    3u      CHR              239,0       0t0        413 /dev/pse
(base) root@host:/# sudo lsof | grep "/dev/pse"
dio       320841                              root    3u      CHR              239,0       0t0        413 /dev/pse

期望:ioctl能填充buf对象,之后可解析为预期的结构体,现在陷入僵局。


解决方法

这个错误的核心原因是Python的fcntl.ioctl处理32位/64位ioctl请求码时的符号扩展问题:你从C代码中拿到的3222292481是无符号整数,但Python会将其当作有符号整数处理,导致请求码被内核错误解析,最终返回误导性的"文件不存在"错误。

具体修复步骤:

  1. 修正ioctl请求码的传递方式:
    直接使用十六进制表示请求码0xC0084801(与十进制3222292481等价),或者用3222292481 & 0xFFFFFFFF确保它被当作无符号32位值传递给内核。

  2. 初始化结构体输入数据:
    C代码中通过memcpy将pse_smhi_guid写入了结构体的in_client_uuid字段,但你的Python代码中buf是全0数组,缺少必要的输入数据,这会导致内核处理失败。需要先将UUID写入buf的对应位置。

修改后的Python代码示例:

import fcntl, array, os

# 替换为实际的pse_smhi_guid字节数据(16字节)
pse_smhi_guid = b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF'

def pse_client_connect():
    device_file = os.open("/dev/pse", os.O_RDWR)
    print(device_file)
    if device_file <= 0:
        print("Failed to open the pse device file\nAre you running as root?\n")
        return
    
    # 用UUID初始化buf,保证输入数据与C代码一致
    buf = array.array('B', pse_smhi_guid)
    # 使用十六进制请求码避免符号扩展问题
    ioctl_request = 0xC0084801
    try:
        ret = fcntl.ioctl(device_file, ioctl_request, buf, True)
        print("ioctl返回值:", ret)
        print("填充后的buf:", buf)
    finally:
        os.close(device_file)

if __name__ == "__main__":
    pse_client_connect()

额外说明:

  • Linux内核的ioctl请求码有固定格式,包含数据方向、大小、类型、编号,用十六进制直接传递能避免数值解析错误。
  • 必须保证buf的大小与C语言中struct ishtp_cc_data的大小完全一致,且输入数据初始化正确,否则内核可能返回其他错误。

内容的提问来源于stack exchange,提问作者Braedon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:49:53