我们有一个包含大量打印消息的守护进程.由于我们使用的嵌入式设备具有较弱的CPU和其他受限硬件,因此我们希望最大限度地降低任何类型的成本(IO、CPU等).我们最终版本中的printf消息.(用户没有控制台)

我的队友和我有分歧.他认为我们可以将所有内容重定向到/dev/null.它不会花费任何IO,所以感情将是最小的.但我认为它仍然需要CPU,我们最好为printf定义一个宏,这样我们就可以重写"printf"(可能只是返回).

所以我需要一些关于谁是对的意见.Linux是否足够智能来优化printf?我真的很怀疑.

推荐答案

差不多.

当您将程序的stdout重定向到/dev/null时,对printf(3)的任何调用仍将计算所有参数,并且字符串格式化过程仍将在调用write(2)之前进行,后者将完整格式化的字符串写入进程的标准输出.在内核级别,数据不会写入磁盘,而是被与特殊设备/dev/null相关联的处理程序丢弃.

因此,在最好的情况下,只需将stdout重定向到/dev/null,就不会绕过或回避计算参数并将其传递到printf的开销,printf后面的字符串格式化工作,以及至少一个实际写入数据的系统调用.这在Linux上是一个真正的区别.该实现只返回要写入的字节数(由对write(2)的调用的第三个参数指定),而忽略其他所有内容(请参见this answer).根据正在写入的数据量和目标设备(磁盘或终端)的速度,性能上的差异可能会有很大的不同.一般来说,在嵌入式系统上,通过重定向到/dev/null来切断磁盘写入可以为大量写入数据节省相当多的系统资源.

虽然从理论上讲,该程序可以检测/dev/null个,并在它们遵循的标准(ISO C和POSIX)的限制内执行一些优化,但基于对常见实现的一般理解,它们实际上不能(即我不知道有任何Unix或Linux系统在这样做).

POSIX标准要求对printf(3)的任何调用写入标准输出,因此根据相关文件描述符 suppress 对write(2)的调用是不符合标准的.有关POSIX要求的更多详细信息,请阅读Damon's answer.哦,还有一个简短的提示:所有Linux发行版实际上都是POSIX兼容的,尽管不是certified.

请注意,如果完全更换printf,可能会出现一些副作用,例如printf("%d%n", a++, &b).如果您真的需要根据程序执行环境来 suppress 输出,请考虑在打印之前设置全局标志并包装PrtTF来判断标志——它不会在性能损失可见的范围内使程序慢下来,作为一个条件判断,它比调用printf并进行所有字符串格式化要快much.

C++相关问答推荐

Mise()在虚拟内存中做什么?

如何判断宏参数是否为C语言中的整型文字

Tiva TM4C123GXL的I2C通信

在C中使用JMP_buf数组进行线程化(在xv6中测试)

从组播组地址了解收到的数据包长度

#If指令中未定义宏?

从纯C中访问通用项对话框

ATmega328P EEPROM未写入

1处的解析器错误:yacc语法的语法错误

在C++中访问双指针

C语言中的外部关键字

GetText不适用于包含国际字符的帐户名称

我正在try 将QSORT算法实现为C++中的泛型函数

Valgrind用net_pton()抱怨

从整型转换为浮点型可能会改变其值.

在C中使用字符串时是否不需要内存分配?

我可以使用Windows SDK';s IN6_IS_ADDR_LOOPBACK等,尽管没有文档?

在同一范围内对具有相同类型的变量执行的相同操作在同一C代码中花费的时间不同

如何使 clangd 启用仅标头库实现

为什么这段代码中 free() 会导致程序崩溃?