为什么我的长时间运行的 python 脚本在运行大约 3 天后会因“无效指针”而崩溃?

2023-12-24

我编写了一个 python 3 脚本来测试 SPI 与 FPGA 的链接。它在 Raspberry Pi 3 上运行。测试的工作原理如下:将 FPGA 置于测试模式(按钮开关)后,发送第一个字节,该字节可以是任何值。然后无限期地发送更多字节。每个值按发送的第一个值递增,截断为 8 位。因此,如果第一个值为 37,则 FPGA 期望以下序列:

37、74、111、148、185、222、4、41 ...

一些额外的 IO 引脚用于在设备之间发出信号 - RUN(RPi 输出)启动测试(这是必要的,因为如果 FPGA 需要一个字节,它会在大约 15ms 内超时),ERR(FPGA 输出)发出错误信号。因此可以在两端计算错误。

此外,RPi 脚本会写入一行摘要,其中包含发送的字节数和每百万字节的错误数。

所有这些都工作得很好。但运行了大约 3 天后,我在 RPi 上收到以下错误:

free():无效指针:0x00405340

我在两个相同的测试设置上得到了完全相同的错误,甚至是相同的内存地址。最后一份报告说 “已发送 4294M 字节,0 个错误”

我似乎已经证明了 SPI 链接,但我担心这个长时间运行的程序会无缘无故地崩溃。

这是我的测试代码的重要部分:

def _report(self, msg):
        now = datetime.datetime.now()
        os.system("echo \"{} : {}\" > spitest_last.log".format(now, msg))

    def spi_test(self):
        global end_loop
        input("Put the FPGA board into SPI test mode (SW1) and press any key")
        self._set_run(True)
        self.END_LOOP = False
        print("SPI test is running, CTRL-C to end.")
        # first byte is sent without LOAD, this is the seed
        self._send_byte(self._val)
        self._next_val()
        end_loop = False
        err_flag = False
        err_cnt = 0
        byte_count = 1
        while not end_loop:
            mb = byte_count % 1000000 
            if mb == 0:
                msg = "{}M bytes sent, {} errors".format(int(byte_count/1000000), err_cnt)
                print("\r" + msg, end="")
                self._report(msg)
                err_flag = True
            else:
                err_flag = False
            #print("sending: {}".format(self._val))
            self._set_load(True)
            if self._errors and err_flag:
                self._send_byte(self._val + 1)
            else:
                self._send_byte(self._val)
            if self.is_error():
                err_cnt += 1
                msg = "{}M bytes sent, {} errors".format(int(byte_count/1000000), err_cnt)
                print("\r{}".format(msg), end="")
                self._report(msg)
            self._set_load(False)
            # increase the value by the seed and truncate to 8 bits
            self._next_val()
            byte_count += 1

        # test is done
        input("\nSPI test ended ({} bytes sent, {} errors). Press ENTER to end.".format(byte_count, err_cnt))
        self._set_run(False)

(澄清注意:有一个命令行选项可以人为地每百万字节创建一个错误。因此有“err_flag”变量。)

我尝试在控制台模式下使用 python3,并且 byte_count 变量的大小似乎没有问题(根据我读过的有关 python 整数大小限制的内容,不应该有问题)。

任何人都知道可能会导致这种情况的原因是什么?


此问题仅与 3.5 之前的 spidev 版本有关。下面的评论是在假设我使用 spidev 的升级版本的情况下完成的。

#################################################### ############################

我可以确认这个问题。它对于 RPi3B 和 RPi4B 都是持久的。在 RPi3 和 RPi4 上使用 python 3.7.3。我尝试过的spidev版本是3.3、3.4和最新的3.5。通过简单地循环这一行,我能够多次重现此错误。

spidevice2.xfer2([0x00, 0x00, 0x00, 0x00])

根据 RPi 版本,最多需要 11 小时。在 1073014000 次调用(四舍五入到 1000)之后,脚本因“无效指针”而崩溃。发送的总字节数与中相同danmcb的情况。看起来 2^32 字节代表了一个限制。

我尝试了不同的方法。例如,时不时地调用 close(),然后调用 open()。这没有帮助。

然后,我尝试在本地创建 spiDev 对象,以便为每批数据重新创建它。

def spiLoop():
    spidevice2 = spidev.SpiDev()
    spidevice2.open(0, 1)
    spidevice2.max_speed_hz = 15000000
    spidevice2.mode = 1 # Data is clocked in on falling edge
    
    for j in range(100000):
        spidevice2.xfer2([0x00, 0x00, 0x00, 0x00])
        
    spidevice2.close()

大约之后它仍然崩溃。 xfer2([0x00, 0x00, 0x00, 0x00]) 的 2^30 次调用相当于大约2^32 字节。

EDIT1

为了加快该过程,我使用下面的代码以 4096 字节的块进行发送。我在本地反复创建了 SpiDev 对象。花了 2 个小时才达到 2^32 字节数。

def spiLoop():
    spidevice2 = spidev.SpiDev()
    spidevice2.open(0, 1)
    spidevice2.max_speed_hz = 25000000
    spidevice2.mode = 1 # Data is clocked in on falling edge
    
    to_send = [0x00] * 2**12 # 4096 bytes
    for j in range(100):
        spidevice2.xfer2(to_send)
        
    spidevice2.close()
    del spidevice2

def runSPI():
    for i in range(2**31 - 1):
        spiLoop()            
        print((2**12 * 100 * (i + 1)) / 2**20, 'Mbytes')

EDIT2

即时重新加载 spidev 也没有帮助。我在 RPi3 和 RPi4 上尝试了此代码,结果相同:

import importlib
def spiLoop():
    importlib.reload(spidev)
    spidevice2 = spidev.SpiDev()
    spidevice2.open(0, 1)
    spidevice2.max_speed_hz = 25000000
    spidevice2.mode = 1 # Data is clocked in on falling edge
    
    to_send = [0x00] * 2**12 # 4096 bytes
    for j in range(100):
        spidevice2.xfer2(to_send)
        
    spidevice2.close()
    del spidevice2

def runSPI():
    for i in range(2**31 - 1):
        spiLoop()            
        print((2**12 * 100 * (i + 1)) / 2**20, 'Mbytes')

EDIT3

执行代码片段也没有隔离问题。在发送第 4 个 1G 字节数据后,它崩溃了。

program = '''
import spidev
spidevice = None

def configSPI():
    global spidevice
    
    # We only have SPI bus 0 available to us on the Pi
    bus = 0
    #Device is the chip select pin. Set to 0 or 1, depending on the connections
    device = 1

    spidevice = spidev.SpiDev()
    spidevice.open(bus, device)
    spidevice.max_speed_hz = 250000000
    
    spidevice.mode = 1 # Data is clocked in on falling edge

def spiLoop():
    to_send = [0xAA] * 2**12
    loops = 1024
    for j in range(loops):
        spidevice.xfer2(to_send)
    
    return len(to_send) * loops    

configSPI()
bytes_total = 0

while True:
    bytes_sent = spiLoop()
    bytes_total += bytes_sent            
    print(int(bytes_total / 2**20), "Mbytes", int(1000 * (bytes_total / 2**30)) / 10, "% finished")
    if bytes_total > 2**30:
        break

'''
for i in range(100):
    exec(program)
    print("program executed", i + 1, "times, bytes sent > ", (i + 1) * 2**30)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我的长时间运行的 python 脚本在运行大约 3 天后会因“无效指针”而崩溃? 的相关文章

  • 如何屏蔽 PyTorch 权重参数中的权重?

    我正在尝试在 PyTorch 中屏蔽 强制为零 特定权重值 我试图掩盖的权重是这样定义的def init class LSTM MASK nn Module def init self options inp dim super LSTM
  • 带圆角的 Seaborn 条形图

    我正在尝试绘制一些条形图 但想控制角的圆度 我尝试按照堆栈问题中提供的答案进行操作Matplotlib 中带圆角的条形图 https stackoverflow com questions 58425392 bar chart with r
  • Dask DataFrame 的逐行处理

    我需要处理一个大文件并更改一些值 我想做这样的事情 for index row in dataFrame iterrows foo doSomeStuffWith row lol doOtherStuffWith row dataFrame
  • NLTK、搭配问题:需要解包的值太多(预期为 2)

    我尝试使用 NLTK 检索搭配 但出现错误 我使用内置的古腾堡语料库 I wrote alice nltk corpus gutenberg fileids 7 al nltk corpus gutenberg words alice al
  • 当x轴不连续时如何删除冗余日期时间 pandas DatetimeIndex

    我想绘制一个 pandas 系列 其索引是无数的 DatatimeIndex 我的代码如下 import matplotlib dates as mdates index pd DatetimeIndex 2000 01 01 00 00
  • 如何使用 openpyxl 对工作簿中的 Excel 工作表/选项卡进行排序

    我需要按字母数字对工作簿中的选项卡 工作表进行排序 我在用openpyxl https openpyxl readthedocs io en default 操作工作表 您可以尝试排序workbook sheets list workboo
  • Python:随时接受用户输入

    我正在创建一个可以做很多事情的单元 其中之一是计算机器的周期 虽然我将把它转移到梯形逻辑 CoDeSys 但我首先将我的想法放入 Python 中 我将进行计数 只需一个简单的操作 counter 1 print counter 跟踪我处于
  • 使用Python将图像转换为十六进制格式

    我的下面有一个jpg文件tmp folder upload path tmp resized test jpg 我一直在使用下面的代码 Method 1 with open upload path rb as image file enco
  • Python 中的这种赋值方式叫什么? a = b = 真

    我知道关于元组拆包 http docs python org tutorial datastructures html tuples and sequences但是当一行中有多个等号时 这个赋值被称为什么 阿拉a b True 它总是让我有
  • Python unicode 字符代码?

    有没有办法将 Unicode 字符 插入 Python 3 中的字符串 例如 gt gt gt import unicode gt gt gt string This is a full block s unicode charcode U
  • 字典的嵌套列表

    我正在尝试创建dict通过嵌套list groups Group1 A B Group2 C D L y x 0 for y in x if y x 0 for x in groups d k v for d in L for k v in
  • 负整数的Python表示

    gt gt gt x 4 gt gt gt print b format x x 4 100 gt gt gt mask 0xFFFFFFFF gt gt gt print b format x mask x mask 4294967292
  • 在 Tkinter 中使用锚点

    我正在尝试对自动点唱机进行编程 但是我还处于早期阶段 并且在使用时遇到了问题anchor 这是我的代码 from tkinter import from tkinter import messagebox as box def main m
  • Python Flask 是否定义了路由顺序?

    在我看来 我的设置类似于以下内容 app route test def test app route
  • WindowsError:[错误 5] 访问被拒绝

    我一直在尝试终止一个进程 但我的所有选项都给出了 Windows 访问被拒绝错误 我通过以下方式打开进程 一个python脚本 test subprocess Popen sys executable testsc py 我想杀死那个进程
  • CSV 在列中查找最大值并附加新数据

    大约两个小时前 我问了一个关于从网站读取和写入数据的问题 从那时起 我花了最后两个小时试图找到一种方法来从输出的 A 列读取最大日期值 将该值与刷新的网站数据进行比较 并将任何新数据附加到 csv 文件而不覆盖旧的或创建重复项 目前 100
  • Pandas 在特定列将数据帧拆分为两个数据帧

    I have pandas我组成的 DataFrameconcat 一行由 96 个值组成 我想将 DataFrame 从值 72 中分离出来 这样 一行的前 72 个值存储在 Dataframe1 中 接下来的 24 个值存储在 Data
  • 将 Scikit-Learn OneHotEncoder 与 Pandas DataFrame 结合使用

    我正在尝试使用 Scikit Learn 的 OneHotEncoder 将 Pandas DataFrame 中包含字符串的列替换为 one hot 编码的等效项 我的下面的代码不起作用 from sklearn preprocessin
  • 具有指定置信区间的 Seaborn 条形图

    我想在 Seaborn 条形图上绘制置信区间 但我已经计算出置信区间 如何让 Seaborn 绘制我的置信区间而不是尝试自行计算它们 例如 假设我有以下 pandas DataFrame x pd DataFrame Group 1 0 5
  • 如何使用 Django (Python) 登录表单?

    我在 Django 中构建了一个登录表单 现在我遇到了路由问题 当我选择登录按钮时 表单不会发送正确的遮阳篷 我认为前端的表单无法从 查看 py 文件 所以它不会发送任何 awnser 并且登录过程无法工作 该表单是一个简单的静态 html

随机推荐