Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / glibc中的printf如何输出到串口

Linux内核版本:2.6.14glibc版本:2.3.6CPU平台:armprintf的输出不一定是串口,也可以是LCD,甚至是文件等,这里仅以输出到串口为例。本文分析了printf和文件描述符0、1和2以及stdout、stdin和stderr的关系,通过这篇文章可以知道文件描述符0、1和2为什么对应着stdout、stdin和stderr,因为glibc就是这么定义的!!!首先看glibc中printf函数的定义(glibc-2.3.6/stdio-common/printf.c):#undef printf/* Write formatted output to stdout from the format string FORMAT.  */
/* VARARGS1 */
int
printf (const char *format, ...)
{
  va_list arg;
  int done;  va_start (arg, format);
  done = vfprintf (stdout, format, arg);//主要是这个函数
  va_end (arg);  return done;
}#undef _IO_printf
/* This is for libg++.  */
strong_alias (printf, _IO_printf);strong_alias,即取别名。网上有人提及这个strong alias好像是为了防止c库符号被其他库符号覆盖掉而使用的,如果printf被覆盖了,还有_IO_printf可以用。跟踪vfprintf函数(),我们先给出该函数的声明,如下(glibc-2.3.6/libio/stdio.h):extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format,
 _G_va_list __arg);printf函数是通过vfprintf将format输出到stdout文件中,stdout是(FILE *)类型。stdout的定义如下(glibc-2.3.6/libio/stdio.h),顺被也给出stdin和stderr的定义:/* Standard streams.  */
extern struct _IO_FILE *stdin;  /* Standard input stream.  */
extern struct _IO_FILE *stdout;  /* Standard output stream.  */
extern struct _IO_FILE *stderr;  /* Standard error output stream.  */
/* C89/C99 say they"re macros.  Make them happy.  */
#define stdin stdin
#define stdout stdout
#define stderr stderr继续跟踪stdout(glibc-2.3.6/libio/stdio.c):_IO_FILE *stdin = (FILE *) &_IO_2_1_stdin_;
_IO_FILE *stdout = (FILE *) &_IO_2_1_stdout_;
_IO_FILE *stderr = (FILE *) &_IO_2_1_stderr_;在继续分析_IO_2_1_stdout_之前,我们先看一下_IO_FILE(FILE和_IO_FILE是一回事,#define FILE _IO_FILE)的定义(glibc-2.3.6/libio/libio.h):struct _IO_FILE {
  int _flags;  /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr; /* Current read pointer */
  char* _IO_read_end; /* End of get area. */
  char* _IO_read_base; /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr; /* Current put pointer. */
  char* _IO_write_end; /* End of put area. */
  char* _IO_buf_base; /* Start of reserve area. */
  char* _IO_buf_end; /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */  struct _IO_marker *_markers;  struct _IO_FILE *_chain;  int _fileno;//这个就是linux内核中文件描述符fd
#if 0
  int _blksize;
#else
  int _flags2;
#endif
  _IO_off_t _old_offset; /* This used to be _offset but it"s too small.  */#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];  /*  char* _save_gptr;  char* _save_egptr; */  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
struct _IO_FILE_plus
{
  _IO_FILE file;
  const struct _IO_jump_t *vtable;//IO函数跳转表
};Glibc 的详细介绍:请点这里
Glibc 的下载地址:请点这里