2016-01-28 72 views
7

我在寫入內存(/ dev/mem)時在python中使用mmap時出現了一個奇怪的問題。 要清楚,閱讀是以相同的方式完成的,它的工作正常。 但是在寫入時,似乎每個第二個字節都是不可寫的。python mmap在編寫時跳過每個第二個字節

ex。

when I read i get 
addr 0x200 val 0x1234 
but when I try to write 
addr 0x200 val 0x4321 
what really is written is 
addr 0x200 val 0x0021 

當我嘗試逐字節寫入時,發生同樣的情況。 ex。

write: 
addr 0x200 0x43 
addr 0x201 0x21 
I get 
addr 0x200 0x00 
addr 0x201 0x21 

代碼:

class Pydump: 
    def __init__(self, addr, length = 1, word_size = 4, filename = '/dev/mem'): 
     if addr < 0 or length < 0: raise ValueError('Address or length invalid') 
     self._verbose = verbose 

     self.word_size = word_size 
     self.mask = ~(self.word_size - 1) 
     self.base_addr = addr & ~(mmap.PAGESIZE - 1) 
     self.addr_offset = addr - self.base_addr 
     self.word_length = length 
     self.no_of_bytes = self.word_length * self.word_size 

     # align length to full words 
     end_addr = addr + self.no_of_bytes 
     if end_addr % self.mask: 
      end_addr = (end_addr + self.word_size) & self.mask 

     self.map_length = end_addr - self.base_addr 
     self.fname = filename 

     self.fd = os.open(self.fname, os.O_RDWR | os.O_SYNC) 
     self.mem = mmap.mmap(self.fd, self.map_length, mmap.MAP_SHARED, 
          mmap.PROT_READ | mmap.PROT_WRITE, 
          offset=self.base_addr) 

    def read(self): 
     mem = self.mem 
     virt_base_addr = self.addr_offset & self.mask 
     mem.seek(virt_base_addr) 

     data = [] 
     for i in range(self.no_of_bytes): 
      data.append(struct.unpack('B', mem.read_byte())[0]) 

     abs_addr = self.base_addr + virt_base_addr 
     return PydumpBuffer(abs_addr, data, self.word_size) 

    def write(self, data): 
     mem = self.mem 
     virt_base_addr = self.addr_offset & self.mask 
     mem.seek(virt_base_addr) 

     if self.word_size == 1: 
      mem.write(struct.pack('B', data)) 
     elif self.word_size == 2: 
      mem.write(struct.pack('H', data)) 
     elif self.word_size == 4: 
      mem.write(struct.pack('I', data)) 
     else: 
      raise ValueError('Invalid word size') 

    def write_bytes(self, bytes): 
     if len(bytes) != self.no_of_bytes: raise ValueError('Wrong number of bytes given') 
     mem = self.mem 
     virt_base_addr = self.addr_offset & self.mask 
     mem.seek(virt_base_addr) 

     for byte in bytes: 
      mem.write_byte(byte) 

實施例運行(I製備與其它memdump工具[二進制]存儲器是0xEEEEEEEE):

>>> from pydump import Pydump as memdump 
>>> memdump(0x18007C20, 1, 4).read() 
0xEEEEEEEE 
>>> memdump(0x18007C20, 1, 4).write(0x12345678) 
>>> memdump(0x18007C20, 1, 4).read() 
0x00340078 
>>> memdump(0x18007C20, 1, 4).write(0x87654321) 
>>> memdump(0x18007C20, 1, 4).read() 
0x00650021 

實施例沒有2(I寫不出甚至在'第一'字節處有2個字節):

>>> memdump(0x18007C20, 1, 2).write(0xABCD) 
>>> memdump(0x18007C20, 1, 4).read() 
0x00650021 
>>> memdump(0x18007C21, 1, 1).write(0xCD) 
>>> memdump(0x18007C20, 1, 4).read() 
0x00650021 
>>> memdump(0x18007C22, 1, 1).write(0xCD) 
>>> memdump(0x18007C20, 1, 4).read() 
0x00CDCD00 

關於可能是什麼問題的想法?

+1

什麼Python版本是您使用?順便說一句,'bytes'不是一個好變量名,因爲它陰影內置['字節'](https://docs.python.org/3/library/functions.html#bytes)類型。請注意,在Python 2中'bytes'實質上是'str'的​​同義詞。 –

+0

我正在使用python 2.7 .10。 – k3tchup

+2

你正在寫的內存是什麼?它是一個內存映射設備嗎?它們可能有特殊要求,因此你可以嘗試用ctypes寫入。 –

回答

0

我知道現在出了什麼問題。 答案是,它和我的特定硬件/驅動程序一樣是python的錯。

我查看了mmap的實現,它使用了memcpy,正如我們所知,它是逐字節拷貝的。在C實現中,這沒有發生,當我們需要寫入4個字節時,寫入了4個字節。 因此,我的硬件/驅動程序的侷限性在於每個寄存器都必須全部寫入(在說明問題時我不知道這一點),因此當逐字節地寫入時,我會產生奇怪的行爲。

一些寄存器是16位,有些是32位。 當我寫0xFFFF到16位寄存器時,我結束了0x00FF。所以memcpy複製0xFF兩次。我的驅動程序寫入(0xFF)然後寫入(0xFF),所以我實際上在做什麼(由於python)是兩次寫入字節0xFF的寄存器:) 也許32位寄存器發生了同樣的情況,雖然看起來不同駕駛員也可能表現不同)。

對於它的工作,我將不得不改變蟒蛇MMAP :(實施

相關問題