在 Newlib 中你没有实现printf()
包含在库中。您只需实现一组最小的系统调用即可支持该库。流设备 sycalls API 包括open
, close
, read
and write
(或可重入版本_r
后缀) - 如果您使用多线程并且需要每个线程,则重入性非常有用errno
(在任何实施特定的重入要求中)。
如果你正在实施的只是stdout
(使用的流printf()
, putchar()
, puts()
等)并且仅支持单个设备(通常是 UART)并且不关心重定向或重入的能力,那么open
, close
and read
可以为空,并且write
可以简单地将提供的缓冲区直接输出到低级串行 I/O API:
int _write(int handle, char *data, int size )
{
int count ;
handle = handle ; // unused
for( count = 0; count < size; count++)
{
outputByte( data[count] ) ; // Your low-level output function here.
}
return count;
}
注意handle
这里是未使用的。为了stdout
它将是 1 (stdin
= 0 和stderr
= 2).这handle
如果您想要单独的输出设备,则将使用参数stdout
and stderr
或者如果您支持其他设备或文件系统并且fopen
or stdout
重定向。它用于识别打开的蒸汽open
。通过忽略所有流输出(例如fprintf()
将以相同的方式处理并输出到相同的设备);在许多情况下(其中printf()
只是获取调试输出的一种方法,或者您的应用程序没有您不会关心的文件系统。
鉴于write
功能,printf()
将“正常工作”(以最简单的方式),因为在幕后所有 stdio 输出函数都调用write
)。建议使用缓冲且非阻塞的低电平输出函数(例如中断驱动的 UART 驱动程序)。
显然如果你想接受input on stdin
你也可以实现类似的read
功能。
如果你想要一个堆(malloc()
等)你还需要实施sbrk
/ sbrk_r
。如果 Newlib 系统调用中没有其他内容,我建议您至少实现这一点。
Bill Gaitliff 在 中讨论了对系统调用实现的更复杂的处理在嵌入式系统中移植和使用 Newlib,而基本实现则在here而示例中提供了与上面类似的最小实现存根Newlib 文档 itself.