On Linux setup, I am trying to write device file using python's mmap
.
Following is the code snippet:
import struct, os, mmap, sys
def write(addr, size, data):
filename = "<pci_device_file>/resource0";
# page size of this setup (typically 4k)
psize = os.sysconf("SC_PAGE_SIZE")
# mmap expects offsets to be multiple of page-size
base_offset = int(addr // psize) * psize
# offset within the page
seek_sz = int(addr % psize)
# total bytes to be mapped = offset within the page + requested size
map_size = seek_sz + size
# open the dev file (of mem)
fd = os.open(filename, os.O_RDWR|os.O_SYNC)
# map the dev file to process address space
mem = mmap.mmap(fd, map_size,
mmap.MAP_SHARED,
mmap.PROT_READ|mmap.PROT_WRITE,
offset=base_offset)
# goto the target offset (within the page that is mapped)
mem.seek(seek_sz, os.SEEK_SET)
val = mem.read(size)
print ('Packed val read = {}'.format(val))
print(hex(struct.unpack("I", val)[0]))
# seek to same offset, now to write
mem.seek(seek_sz, os.SEEK_SET)
# pack the data
packed_data = struct.pack("I", data)
print('Packed val write = {}'.format(packed_data))
# write to memory
ret_code = mem.write(packed_data)
# try to re-read the value written
mem.seek(seek_sz, os.SEEK_SET)
val = mem.read(size)
print ('Packed val read (after write) = {}'.format(val))
print(hex(struct.unpack("I", val)[0]))
# close fd
os.close(fd)
return ret_code
write(0x4330, 4, int(sys.argv[1], 16))
When I run this code, I get the following output:
root@linux$ python3 /ssd/my_mmap.py 0x113d0000
Packed val read = b'\x00\x00="'
0x223d0000
Packed val write = b'\x00\x00=\x11'
Packed val read (after write) = b'\x00\x00="'
0x223d0000 ==> value not written
The address is writable and I could write it using C program. However, with python program, it was never able to write. Base-address, offset etc. values are correct - as I could read the old values using the same.
What am I missing? Sigh!
Wanted to update this for other's benefit.
I guess, I was using the mmap
wrongly.
I needed to open the device file using built-in open
instead of os.open
.
For some reason, that made a difference, though not sure why the latter did not work.
As given in the link https://www.tutorialspoint.com/memory-mapped-file-support-in-python-mmap , after I modified the code to use built-in open
I was able to write the contents (both in pci device file and the regular file).
import mmap
def mmap_io_write(fname):
with open(fname, mode="r+") as fobj:
with mmap.mmap(fobj.fileno(), length=0, access=mmap.ACCESS_WRITE) as mmap_obj:
mmap_obj[20:26] = b"Hello!"
mmap_obj.flush()