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