我听说 C 中的 printf() 不应该在 ISR 中使用。是因为它是一个阻塞调用,还是因为它不是可重入的?
如果 printf() 不是可重入的,那么这是否意味着它也不能用于多线程程序,除非它以某种方式“同步”?
谢谢,
我听说 C 中的 printf() 不应该在 ISR 中使用。是因为它是一个阻塞调用,还是因为它不是可重入的?
如果 printf() 不是可重入的,那么这是否意味着它也不能用于多线程程序,除非它以某种方式“同步”?
谢谢,
我认为可能是所有这些,甚至更多。典型的printf()
实现可以进行动态(堆)内存分配,这通常不是最快的事情,并且也可能存在不可重入的问题。快速性很重要,因为您通常不应该在中断服务程序上花费太多时间。
有关和的讨论,请参见此答案。printf()
malloc()
它不应该在 ISR 中,因为它不是可重入的,也不是线程安全的,但主要是因为它是一个非常巨大的函数,如果你从 ISR 调用它,它会锁定整个程序,从而立即产生极端的中断抖动杀死程序中实时性能的每一个提示。
巨大的、夸张的函数不应该出现在 ISR 中,无论它们是否是线程安全的!
我将假设您的意思是中断,即使内核中的中断处理程序通常有更多的特殊限制。相同的论点适用于信号处理程序,但它通常比中断处理程序的特殊限制更简单。如果我的假设是错误的,只需将答案中的“中断”替换为“信号”即可。
函数可以是线程安全的,而不是信号/中断安全的。如果函数使用锁保护其内部状态,然后在获得中断时持有该锁,则中断处理程序无法获取该锁,因为持有该锁的执行路径被中断阻塞。要释放锁,您必须退出中断处理程序,恢复线程的执行直到锁被释放,然后返回中断处理程序。这通常是不可行的,除非您的内核已将中断处理程序实现为可以在等待锁定时产生执行的线程。
使函数同时中断和线程安全的一种常规方法是在持有锁的同时阻止中断,但这非常昂贵,除非非常必要,否则不会这样做。
我听说 C 中的 printf() 不应该在 ISR 中使用。是因为它是一个阻塞调用,还是因为它不是可重入的?
更准确地说,因为printf()
它不是异步信号安全功能。请参阅Signal Concepts底部的 async-signal-safe 列表。
如果你从那里调用 printf() ,它可能会工作,也许一两次。如果它试图阻塞,那几乎是一场灾难,因为中断处理程序没有线程上下文。
如果你在嵌入的东西上链接多线程库, printf() 将获得一个互斥锁,以确保从多个线程调用它是安全的。
正如其他海报所说,只是不要从中断处理程序中调用这些东西。信号量单元总是安全的,IME。仅在操作系统文档中特别注明的其他内容。