gpt4 book ai didi

python - CUSE IOCTL 使用包含指向字符数组的指针的结构进行回复

转载 作者:太空宇宙 更新时间:2023-11-03 17:26:42 24 4
gpt4 key购买 nike

ctypesFUSECUSE部分的帮助下,我正在Python的用户空间中实现一个设备驱动程序。这不是我的第一个 CUSE 驱动程序,过去我能够执行以下操作来返回结构。

class tvStruct(Structure):
_fields_ = [("tv_sec",c_long),
("tv_usec",c_long)]

timeval 结构可以传递回使用具有适当编号的 IOCTL 调用的应用程序。以下是CUSE驱动程序的IOCTL文件操作。

def ioctl(self, req, cmd, arg_p, file_info, uflags, in_buff_p, in_bufsz, out_bufsz):
ioctl = DECODE_IOC(cmd)
if ioctl == IOC_READ_TIMEVAL:
if not in_buff_p:
PyCuse.fuse_reply_ioctl_retry(req,
pointer(PyCuse.iovec(cast(arg_p,c_void_p),
sizeof(tvStruct))),1,
pointer(PyCuse.iovec(cast(arg_p,c_void_p),
sizeof(tvStruct))),1)
else:
tvPtr = cast(in_buff_p,POINTER(tvStruct))
PyCuse.fuse_reply_ioctl(req, 0, tvPtr, sizeof(tvStruct))
else:
print("%s Unrecognized IOCTL #...\n",self.devname)
PyCuse.fuse_reply_err(req,1)

我正在开发的当前驱动程序需要返回一个包含指向字符数组的指针的结构。

# C++ Struct
typedef struct {
__u16 addr;
__u16 length;
__u8* pBuf;
} EEPromData;

# Python Class
class EEPromDataStruct(Structure):
_fields_ = [("addr",c_ushort),
("length",c_ushort),
("pBuf",POINTER(c_char))] # I have tried several other ctypes types
# for `pBuf`, but to no avail yet

我知道我无法将 Python 中的指针分配给 pBuf,因为它不是相同的内存上下文。我还了解到,使用 copy_to_user 从内核空间实现这一点有些容易。我受到要求,这是一个Python应用程序,因为它附加到一个Python GUI。我感谢任何和所有的帮助。

更新 1

我知道这个问题可以通过fuse_reply_ioctl_retry方法来解决。此方法允许我从应用程序复制数据或将数据复制到应用程序。现在的问题是,在第二次调用 fuse_reply_ioctl_retry 时,FUSE 会向应用程序返回错误代码。我将继续尝试解决此问题,但同时希望得到任何帮助。谢谢。

最佳答案

我已经弄清楚了。诀窍是为结构中要访问其内容的每个指针调用fuse_reply_ioctl_retry,无论是修改它们还是只是读取它们。事实证明,使用 pythonctypes 以及 FUSE/CUSE 非常麻烦,如果其他人这样做,我强烈建议切换对于这个应用程序,直接使用 C 语言是因为 ctypes 可能已经足够棘手了,但在 CUSE/FUSE 系统之上,它是非常可怕的。我会的,但我必须使用 python,因为这是另一个应用程序的附加组件。小咆哮结束了。

这是该解决方案的精简版本。

# ctypes Structure for driver
class EEPromDataStruct(Structure):
_fields_ = [("addr",c_ushort),
("length",c_ushort),
("pBuf",c_ulong)] #u8*
# Note that this is a long instead of some pointer.
# This is so I can easily know the application address
# the pointer holds.
...

# The IOCTL file operation for this driver
def ioctl(self, req, cmd, arg_p, file_info, uflags, in_buff_p,
in_bufsz, out_bufsz):
ioctl = DECODE_IOC(cmd)
if ioctl == IOC_READ_EEPROM:
if not in_buff_p:
PyCuse.fuse_reply_ioctl_retry(req,pointer(PyCuse.iovec(
cast(arg_p,c_void_p),sizeof(
EEPromDataStruct))),1,None,0)
else:
if out_bufsz == 0:
eepromDataPtr = cast(in_buff_p,POINTER(EEPromDataStruct))
addr = eepromDataPtr.contents.addr
length = eepromDataPtr.contents.length
pBuf = eepromDataPtr.contents.pBuf
# Load from pBuf
out_iovecs = pointer(PyCuse.iovec(cast(pBuf,c_void_p),length))
in_iovecs = pointer(PyCuse.iovec(cast(pBuf,c_void_p),length))
PyCuse.fuse_reply_ioctl_retry(req,in_iovecs,1,out_iovecs,1)
else:
eepromBuff.value = "Some String Here"
PyCuse.fuse_reply_ioctl(req, 0, eepromBuff, out_bufsz)
else:
print("%s Unrecognized IOCTL #...\n",self.devname)
PyCuse.fuse_reply_err(req,1)

if not in_buff_p 将检查应用程序内存是否已加载到驱动程序中,如果没有,它将调用 fuse_reply_ioctl_retry 来执行此操作。请注意,现在的一个主要区别是为此重试指定的输出数据向量为None。这很重要,因为我随后会检查输出大小是多少。如果它是 0,那么我知道它是我的主要 EEPromDataStruct 并且我继续沿着该路径。我准备一些数据向量并重试。最后,我获取指针并为其内容分配一些字符串。

这是一个漫长的过程。但它有效。我希望这对有需要的人有帮助。

关于python - CUSE IOCTL 使用包含指向字符数组的指针的结构进行回复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32466209/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com