转换 mmap 对象(mmap 不支持串联)/将 c 代码转换为 python

Convert mmap object (mmaps don't support concatenation) / convert c code to python

大家好,我正在尝试将下面的代码转换为 python(访问 raspberry pi 1Mhz 计时器),我不知道什么时候需要 mmap 对象 + TIMER_OFFSET (timer = (long long int *)((char *)st_base + TIMER_OFFSET);) 当我在 Python 中尝试这样做时,我得到了 SystemError: mmaps don't support concatenation。我一直在寻找转换 mmap 对象,但我什么也没找到,我们可以解决这个问题吗?可以将整个代码转换为 python 吗?我的意思是现在我对它有了第二个想法?

#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define ST_BASE (0x3F003000)
#define TIMER_OFFSET (4)

int main(int argc, char *argv[]) {
    long long int t, prev, *timer; // 64 bit timer
    int fd;
    void *st_base; // byte ptr to simplify offset math

    // get access to system core memory
    if (-1 == (fd = open("/dev/mem", O_RDONLY))) {
        fprintf(stderr, "open() failed.\n");
        return 255;
    }

    // map a specific page into process's address space
    if (MAP_FAILED == (st_base = mmap(NULL, 4096,
                        PROT_READ, MAP_SHARED, fd, ST_BASE))) {
        fprintf(stderr, "mmap() failed.\n");
        return 254;
    }

    // set up pointer, based on mapped page
    timer = (long long int *)((char *)st_base + TIMER_OFFSET); //<- here is problem

    // read initial timer
    prev = *timer;
    // and wait
    sleep(1);

    while (1==1) { // forever
        // read new timer
        t = *timer;
        printf("Timer diff = %lld    \r", prev);
        fflush(stdout);
        // save current timer
        prev = t;
        // and wait
        sleep(1);
    }
    // will never get here
    return 0;
}

Python 代码(现在我跳过这个 ifs):

ST_BASE = 0x3F003000
TIMER_OFFSET = 4
import struct
sizeof_long_long = struct.calcsize('q')

def timer():
    while True:
        fd = os.open("/dev/mem",os.O_RDWR | os.O_SYNC)
        stBase = mmap.mmap(fileno=fd,length=4096,offset=ST_BASE)
        timer_bytes = stBase[TIMER_OFFSET:TIMER_OFFSET + sizeof_long_long]
        #print(timer_bytes)
        timer_value, = struct.unpack('q', timer_bytes)
        print(timer_value)
        os.close(fd)

Python 中的 mmap 对象与 C 中的指针有很大不同。mmap 对象的行为很像 bytearray,其中一些额外的方法。然而,bytearray 接口在这里是最有用的。 C 代码将偏移量添加到基地址以获得指向计时器值的第一个字节的指针,然后将其转换为指向 long long int 的指针。在 Python 中,我们可以通过 切片 bytearray 的一部分来做类似的事情,特别是从偏移量开始的 sizeof (long long int) 字节,并使用 struct解码值的模块。

因此我们得到类似

的东西
import struct
sizeof_long_long = struct.calcsize('q')

...


    timer_bytes = stBase[TIMER_OFFSET:TIMER_OFFSET + sizeof_long_long]
    print(timer_bytes)

    # struct.unpack would return a tuple of one element, note the comma.
    timer_value, = struct.unpack('q', timer_bytes)
    print(timer_value)

差不多好了:)只是unpack_from而不是解压

import os, mmap, sys
import struct

ST_BASE = 0x3F003000
TIMER_OFFSET = 4
sizeof_long_long = struct.calcsize("Q")
LENGTH = TIMER_OFFSET + sizeof_long_long

def timer():
    fd = os.open("/dev/mem", os.O_RDONLY | os.O_SYNC)
    stBase = mmap.mmap(fileno=fd, length=4096, access=mmap.ACCESS_COPY, offset=ST_BASE)
    os.close(fd)

    while True:
        timer_value = struct.unpack_from("Q", stBase, TIMER_OFFSET)[0]
        print("timer_value")