在我的Python(2.7.3)代码中,我正在尝试使用ioctl调用,接受long int(64位)作为参数。我在64位系统上,因此64位int与指针大小相同。
我的问题是Python似乎不接受64位int作为fcntl.ioctl()调用的参数。它很乐意接受32位int或64-位指针 - 但我需要的是传递一个64位的int。
这是我的ioctl处理程序:
static long trivial_driver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
long err = 0;
switch (cmd)
{
case 1234:
printk("=== (%u) Driver got arg %lx; arg<<32 is %lx\n", cmd, arg, arg<<32);
break;
case 5678:
printk("=== (%u) Driver got arg %lx\n", cmd, arg);
break;
default:
printk("=== OH NOES!!! %u %lu\n", cmd, arg);
err = -EINVAL;
}
return err;
}
在现有的C代码中,我使用这样的调用:
static int trivial_ioctl_test(){
int ret;
int fd = open(DEV_NAME, O_RDWR);
unsigned long arg = 0xffff;
ret = ioctl(fd, 1234, arg); // ===(1234) Driver got arg ffff; arg<<32 is ffff00000000
arg = arg<<32;
ret = ioctl(fd, 5678, arg); // === (5678) Driver got arg ffff00000000
close(fd);
}
在python中,我打开设备文件,然后得到以下结果:
>>> from fcntl import ioctl
>>> import os
>>> fd = os.open (DEV_NAME, os.O_RDWR, 0666)
>>> ioctl(fd, 1234, 0xffff)
0
>>> arg = 0xffff<<32
>>> # Kernel log: === (1234) Driver got arg ffff; arg<<32 is ffff00000000
>>> # This demonstrates that ioctl() happily accepts a 32-bit int as an argument.
>>> import struct
>>> ioctl(fd, 5678, struct.pack("L",arg))
'\x00\x00\x00\x00\xff\xff\x00\x00'
>>> # Kernel log: === (5678) Driver got arg 7fff9eb1fcb0
>>> # This demonstrates that ioctl() happily accepts a 64-bit pointer as an argument.
>>> ioctl(fd, 5678, arg)
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
ioctl(fd, 5678, arg)
OverflowError: signed integer is greater than maximum
>>> # Kernel log: (no change - OverflowError is within python)
>>> # Oh no! Can't pass a 64-bit int!
>>>
Python有没有办法将我的64位参数传递给ioctl()?
答案 0 :(得分:6)
使用Python的fcntl.ioctl()
是否可行这将是系统相关的。跟踪源代码,错误消息来自line 658 of getargs.c
...
else if (ival > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"signed integer is greater than maximum");
RETURN_ERR_OCCURRED;
}
...在我的系统上,/usr/include/limits.h
告诉我......
# define INT_MAX 2147483647
...(推测)(2 ** ((sizeof(int) * 8) - 1)) - 1
。
因此,除非您正在使用sizeof(int)
至少为8
的系统,否则您必须使用ctypes
模块直接调用基础C函数,但它是平台特定的。
假设Linux,这样的事情应该有用......
from ctypes import *
libc = CDLL('libc.so.6')
fd = os.open (DEV_NAME, os.O_RDWR, 0666)
value = c_uint64(0xffff<<32)
libc.ioctl(fd, 5678, value)
答案 1 :(得分:3)
Python的ioctl
中的'arg'符号与C的符号不同。
在python中(同样根据1)它既可以是python整数(也可以是指定32位或64位),也可以是某种缓冲对象(如字符串)。你在Python中并没有真正的“指针”(因此所有底层的体系结构细节 - 如32位或64位地址都被完全隐藏)。
如果我正确理解了你需要的是SET_VAL
首先需要struct.pack(your 64-bit integer)
进入字符串并将此字符串传递给ioctl,而不是直接传递整数。
像这样:
struct.pack('>Q',1<<32)
对于GET_VAL
,您需要再次使用'Q'类型(而非'L')才能正确解包64位整数值。