将 C ioctl/mmap 调用转换为 Python 时出错?
Error converting a C ioctl/mmap call to Python?
我想将 Linux 驱动程序与 Python 一起使用,并且我正在转换我的 C 程序。
我的 C 程序工作正常,但我在 Python 中有一个错误:IOError: [Errno 14] Bad address
我正在使用:
Python 2.7.13(默认,2018 年 6 月 11 日,22:51:25)
[GCC 7.2.0] 在 linux2
我的 OS 是 Petalinux。
这是C程序
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define DUMMY_IOC_MAGIC 'V'
#define DUMMY_START_TX_CYCLIC _IO(DUMMY_IOC_MAGIC, 0)
#define DUMMY_START_TX _IO(DUMMY_IOC_MAGIC, 1)
int main()
{
int fd, j, ret;
int32_t *map_vptr;
size_t number_of_samples = 64;
size_t size_sample = 4;
//////////////////////////////////////////////////////////////////////////////
printf("Init tx.\n");
fd = open("/dev/playback", O_RDWR | O_SYNC);
if (fd < 0) {
printf("Error opening device\n");
return -1;
}
else{
printf("Device is open...\n");
}
//////////////////////////////////////////////////////////////////////////////
map_vptr = (int32_t*) mmap(0, size_sample * number_of_samples, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map_vptr == MAP_FAILED) {
close(fd);
printf("Error mmapping the file\n");
return -1;
}
printf("Mapped.\n");
//////////////////////////////////////////////////////////////////////////////
int32_t *dst_ptr = map_vptr;
int32_t counter = 0;
for (j = 0; j < number_of_samples; ++j) {
dst_ptr[j] = counter;
counter = counter + 2;
}
//////////////////////////////////////////////////////////////////////////////
// start TX transactions
uint32_t tx_total_len = size_sample * number_of_samples;
ret = ioctl(fd, DUMMY_START_TX, &tx_total_len);
if (ret < 0)
{
printf("ioctl() failed, errno=%d\n", errno);
return -1;
}
printf("End tx.\n");
return 0;
}
这是Python程序
import mmap, os, fcntl
#define DUMMY_START_TX _IO('V', 1)
DUMMY_IOC_MAGIC = 'V'
DUMMY_START_TX = ord(DUMMY_IOC_MAGIC) << (4*2) | 1
NUMBER_OF_SAMPLES = 64;
SIZE_SAMPLE = 4
################################################################################
# Open device
print("Init tx.");
fd = os.open("/dev/playback", os.O_RDWR | os.O_SYNC)
if (fd < 0):
print("Error opening device")
exit(-1);
else:
print("Device is open...")
################################################################################
map_vptr = mmap.mmap(length = SIZE_SAMPLE*NUMBER_OF_SAMPLES, prot = mmap.PROT_READ | mmap.PROT_WRITE,
flags = mmap.MAP_SHARED, fileno = fd, offset = 0)
print("Mapped.");
################################################################################
for i in range(0,NUMBER_OF_SAMPLES):
map_vptr.write_byte(chr(i))
################################################################################
# start TX transactions
tx_total_len = SIZE_SAMPLE * NUMBER_OF_SAMPLES
ret = fcntl.ioctl(fd, DUMMY_START_TX, tx_total_len);
fd.close()
print("End tx.");
输出为:
Init tx.
Device is open...
Mapped.
Traceback (most recent call last):
File "tx_server.py", line 28, in <module>
ret = fcntl.ioctl(fd, DUMMY_START_TX, tx_total_len);
IOError: [Errno 14] Bad address
来自 the Python doc:
fcntl.fcntl(fd, op[, arg])
The argument arg
is optional, and defaults to the integer value 0
. When present, it can either be an integer value, or a string. With the argument missing or an integer value, the return value of this function is the integer return value of the C fcntl()
call. When the argument is a string it represents a binary structure, e.g. created by struct.pack()
. The binary data is copied to a buffer whose address is passed to the C fcntl()
call. The return value after a successful call is the contents of the buffer, converted to a string object.
以上对fcntl.ioctl()
同样有效。在您的情况下,您应该使用 struct.pack()
来传递值,而不是直接传递整数,如下所示:
import struct
# ...
tx_total_len = SIZE_SAMPLE * NUMBER_OF_SAMPLES
ptr = struct.pack('I', tx_total_len)
# I == unsigned int of 4 bytes (uint32_t)
ret = fcntl.ioctl(fd, DUMMY_START_TX, ptr)
我想将 Linux 驱动程序与 Python 一起使用,并且我正在转换我的 C 程序。
我的 C 程序工作正常,但我在 Python 中有一个错误:IOError: [Errno 14] Bad address
我正在使用:
Python 2.7.13(默认,2018 年 6 月 11 日,22:51:25) [GCC 7.2.0] 在 linux2
我的 OS 是 Petalinux。
这是C程序
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define DUMMY_IOC_MAGIC 'V'
#define DUMMY_START_TX_CYCLIC _IO(DUMMY_IOC_MAGIC, 0)
#define DUMMY_START_TX _IO(DUMMY_IOC_MAGIC, 1)
int main()
{
int fd, j, ret;
int32_t *map_vptr;
size_t number_of_samples = 64;
size_t size_sample = 4;
//////////////////////////////////////////////////////////////////////////////
printf("Init tx.\n");
fd = open("/dev/playback", O_RDWR | O_SYNC);
if (fd < 0) {
printf("Error opening device\n");
return -1;
}
else{
printf("Device is open...\n");
}
//////////////////////////////////////////////////////////////////////////////
map_vptr = (int32_t*) mmap(0, size_sample * number_of_samples, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map_vptr == MAP_FAILED) {
close(fd);
printf("Error mmapping the file\n");
return -1;
}
printf("Mapped.\n");
//////////////////////////////////////////////////////////////////////////////
int32_t *dst_ptr = map_vptr;
int32_t counter = 0;
for (j = 0; j < number_of_samples; ++j) {
dst_ptr[j] = counter;
counter = counter + 2;
}
//////////////////////////////////////////////////////////////////////////////
// start TX transactions
uint32_t tx_total_len = size_sample * number_of_samples;
ret = ioctl(fd, DUMMY_START_TX, &tx_total_len);
if (ret < 0)
{
printf("ioctl() failed, errno=%d\n", errno);
return -1;
}
printf("End tx.\n");
return 0;
}
这是Python程序
import mmap, os, fcntl
#define DUMMY_START_TX _IO('V', 1)
DUMMY_IOC_MAGIC = 'V'
DUMMY_START_TX = ord(DUMMY_IOC_MAGIC) << (4*2) | 1
NUMBER_OF_SAMPLES = 64;
SIZE_SAMPLE = 4
################################################################################
# Open device
print("Init tx.");
fd = os.open("/dev/playback", os.O_RDWR | os.O_SYNC)
if (fd < 0):
print("Error opening device")
exit(-1);
else:
print("Device is open...")
################################################################################
map_vptr = mmap.mmap(length = SIZE_SAMPLE*NUMBER_OF_SAMPLES, prot = mmap.PROT_READ | mmap.PROT_WRITE,
flags = mmap.MAP_SHARED, fileno = fd, offset = 0)
print("Mapped.");
################################################################################
for i in range(0,NUMBER_OF_SAMPLES):
map_vptr.write_byte(chr(i))
################################################################################
# start TX transactions
tx_total_len = SIZE_SAMPLE * NUMBER_OF_SAMPLES
ret = fcntl.ioctl(fd, DUMMY_START_TX, tx_total_len);
fd.close()
print("End tx.");
输出为:
Init tx.
Device is open...
Mapped.
Traceback (most recent call last):
File "tx_server.py", line 28, in <module>
ret = fcntl.ioctl(fd, DUMMY_START_TX, tx_total_len);
IOError: [Errno 14] Bad address
来自 the Python doc:
fcntl.fcntl(fd, op[, arg])
The argument
arg
is optional, and defaults to the integer value0
. When present, it can either be an integer value, or a string. With the argument missing or an integer value, the return value of this function is the integer return value of the Cfcntl()
call. When the argument is a string it represents a binary structure, e.g. created bystruct.pack()
. The binary data is copied to a buffer whose address is passed to the Cfcntl()
call. The return value after a successful call is the contents of the buffer, converted to a string object.
以上对fcntl.ioctl()
同样有效。在您的情况下,您应该使用 struct.pack()
来传递值,而不是直接传递整数,如下所示:
import struct
# ...
tx_total_len = SIZE_SAMPLE * NUMBER_OF_SAMPLES
ptr = struct.pack('I', tx_total_len)
# I == unsigned int of 4 bytes (uint32_t)
ret = fcntl.ioctl(fd, DUMMY_START_TX, ptr)