Linux 下的printf具体实现 比如从调用printf到字符出现到屏幕上
时间: 2023-12-06 09:43:49 浏览: 69
在 Linux 下,printf 函数的实现是由标准 C 库提供的,通常位于 libc 库中。
当程序调用 printf 函数时,它首先将参数传递给 libc 库中的 printf 实现。printf 函数会根据格式化字符串中的占位符,将参数格式化为指定的输出格式,并将格式化后的字符串存储在内存缓冲区中。
接下来,printf 函数使用 write 系统调用将缓冲区中的数据写入标准输出文件描述符(stdout)。write 系统调用会将缓冲区中的数据写入内核缓冲区,然后再由内核将数据发送到终端设备,最终在屏幕上显示出来。
需要注意的是,printf 函数默认会使用行缓冲,即在输出换行符 \n 或缓冲区满时才会将数据写入内核缓冲区。如果需要立即将数据写入内核缓冲区,可以使用 fflush 函数来刷新缓冲区。
相关问题
重新定向c库函数printf到USART1,由printf调用
在重新定向c库函数printf到USART1之前,需要先初始化USART1的GPIO口和串口配置,这里假设使用的是STM32F4系列的芯片。下面是一个示例代码:
```
#include "stm32f4xx.h"
#include <stdio.h>
// 重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
while(!(USART1->SR & 0x0080));
USART1->DR = (uint8_t) ch;
return ch;
}
int main()
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开GPIO和USART1的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 配置USART1 Tx (PA9) 的 GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 将GPIO与USART1的Tx引脚连接起来
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
// 配置USART1
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
// 测试printf是否正常工作
printf("Hello, World!\n");
while(1);
}
```
在这个示例代码中,我们首先定义了一个名为`fputc`的函数,这个函数是重定向c库函数printf到USART1的关键所在。`fputc`函数会在printf函数调用的时候被自动调用,它将printf中的每个字符一个一个地输出到USART1,并且等待USART1缓冲区准备好下一个字符。
在主函数中,我们首先初始化了GPIO和USART1的时钟,并且配置了USART1的Tx引脚对应的GPIO口。然后,我们将GPIO和USART1的Tx引脚连接起来,并且配置了USART1的波特率、字长、停止位、奇偶校验等参数。最后,我们测试了一下printf是否正常工作,并且进入了一个死循环。
如果你想使用这个示例代码,记得在工程属性中开启`use MicroLIB`和`use float with printf`选项。
为什么printf函数输出到串口需要调用FPUTC函数
在嵌入式系统中,printf函数通常是通过串口输出调试信息,而printf内部是通过标准输出流来输出字符的。但是,标准输出流并不是直接输出到串口的,而是输出到一个缓冲区中,等到缓冲区满了或者调用fflush函数时才会将缓冲区中的内容输出到串口。
因此,为了将printf函数的输出直接输出到串口,需要重定向标准输出流,并实现FPUTC函数。FPUTC函数将每个字符直接输出到串口,而不是先输出到缓冲区。这样,每次调用printf函数时,输出的字符就会直接输出到串口。
相关推荐
![7z](https://img-home.csdnimg.cn/images/20210720083312.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)