glibc中的printf如何输出到串口
glibc版本:2.3.6
CPU平台:arm
printf的输出不一定是串口,也可以是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):
[plain]view plaincopyprint?
- #undefprintf
- /*WriteformattedoutputtostdoutfromtheformatstringFORMAT.*/
- /*VARARGS1*/
- int
- printf(constchar*format,...)
- {
- va_listarg;
- intdone;
- va_start(arg,format);
- done=vfprintf(stdout,format,arg);//主要是这个函数
- va_end(arg);
- returndone;
- }
- #undef_IO_printf
- /*Thisisforlibg++.*/
- strong_alias(printf,_IO_printf);
strong_alias,即取别名。网上有人提及这个strong alias好像是为了防止c库符号被其他库符号覆盖掉而使用的,如果printf被覆盖了,还有_IO_printf可以用。跟踪vfprintf函数(),我们先给出该函数的声明,如下(glibc-2.3.6/libio/stdio.h):
[plain]view plaincopyprint?
- externintvfprintf(FILE*__restrict__s,__constchar*__restrict__format,
- _G_va_list__arg);
[plain]view plaincopyprint?
- /*Standardstreams.*/
- externstruct_IO_FILE*stdin;/*Standardinputstream.*/
- externstruct_IO_FILE*stdout;/*Standardoutputstream.*/
- externstruct_IO_FILE*stderr;/*Standarderroroutputstream.*/
- /*C89/C99saytheyremacros.Makethemhappy.*/
- #definestdinstdin
- #definestdoutstdout
- #definestderrstderr
[plain]view plaincopyprint?
- _IO_FILE*stdin=(FILE*)&_IO_2_1_stdin_;
- _IO_FILE*stdout=(FILE*)&_IO_2_1_stdout_;
- _IO_FILE*stderr=(FILE*)&_IO_2_1_stderr_;
[plain]view plaincopyprint?
- struct_IO_FILE{
- int_flags;/*High-orderwordis_IO_MAGIC;restisflags.*/
- #define_IO_file_flags_flags
- /*ThefollowingpointerscorrespondtotheC++streambufprotocol.*/
- /*Note:Tkusesthe_IO_read_ptrand_IO_read_endfieldsdirectly.*/
- char*_IO_read_ptr;/*Currentreadpointer*/
- char*_IO_read_end;/*Endofgetarea.*/
- char*_IO_read_base;/*Startofputback+getarea.*/
- char*_IO_write_base;/*Startofputarea.*/
- char*_IO_write_ptr;/*Currentputpointer.*/
- char*_IO_write_end;/*Endofputarea.*/
- char*_IO_buf_base;/*Startofreservearea.*/
- char*_IO_buf_end;/*Endofreservearea.*/
- /*Thefollowingfieldsareusedtosupportbackingupandundo.*/
- char*_IO_save_base;/*Pointertostartofnon-currentgetarea.*/
- char*_IO_backup_base;/*Pointertofirstvalidcharacterofbackuparea*/
- char*_IO_save_end;/*Pointertoendofnon-currentgetarea.*/
- struct_IO_marker*_markers;
- struct_IO_FILE*_chain;
- int_fileno;//这个就是linux内核中文件描述符fd
- #if0
- int_blksize;
- #else
- int_flags2;
- #endif
- _IO_off_t_old_offset;/*Thisusedtobe_offsetbutitstoosmall.*/
- #define__HAVE_COLUMN/*temporary*/
- /*1+columnnumberofpbase();0isunknown.*/
- unsignedshort_cur_column;
- signedchar_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_FILEfile;
- conststruct_IO_jump_t*vtable;//IO函数跳转表
- };
下面我们看看_IO_2_1_stdout_的定义(glibc-2.3.6/libio/stdfiles.c),顺便给出_IO_2_1_stdin_和_IO_2_1_stderr_的定义:
[plain]view plaincopyprint?
- #defineDEF_STDFILE(NAME,FD,CHAIN,FLAGS)\
- struct_IO_FILE_plusNAME\
- ={FILEBUF_LITERAL(CHAIN,FLAGS,FD,NULL),\
- &_IO_file_jumps};
- DEF_STDFILE(_IO_2_1_stdin_,0,0,_IO_NO_WRITES);
- DEF_STDFILE(_IO_2_1_stdout_,1,&_IO_2_1_stdin_,_IO_NO_READS);
- DEF_STDFILE(_IO_2_1_stderr_,2,&_IO_2_1_stdout_,_IO_NO_READS+_IO_UNBUFFERED);
从这里我们可以看到,_IO_2_1_stdout_的FD = 0、_IO_2_1_stdin_的FD = 1、_IO_2_1_stder
glibcprintf输出串 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
