linux 串口格式化输出字符串,glibc中的printf如何输出到串口

下面我们看看_IO_2_1_stdout_的定义(glibc-2.3.6/libio/stdfiles.c),顺便给出_IO_2_1_stdin_和_IO_2_1_stderr_的定义:

#  define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \

struct _IO_FILE_plus NAME \

= {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_stderr_的FD = 2。FILEBUF_LITERAL用于初始化_IO_FILE,定义如下(glibc-2.3.6/libio/libioP.h):

#  define FILEBUF_LITERAL(CHAIN, FLAGS, FD, WDP) \

{ _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (_IO_FILE *) CHAIN, FD, \

0, _IO_pos_BAD, 0, 0, { 0 }, 0, _IO_pos_BAD, \

0 }

其中,FD赋值给了_fileno。我们回到vfprintf的分析,vfprintf的具体实现本文就不详细讲解,主要原理是格式化字符串,最后将字符串输出到文件中,也就是stdout中。至于如何输出,则和_IO_file_jumps关系密切,_IO_file_jumps的定义如下:

const struct _IO_jump_t _IO_file_jumps =

{

JUMP_INIT_DUMMY,

JUMP_INIT(finish, INTUSE(_IO_file_finish)),

JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),

JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),

JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),

JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),

JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),

JUMP_INIT(xsgetn, INTUSE(_IO_file_xsgetn)),

JUMP_INIT(seekoff, _IO_new_file_seekoff),

JUMP_INIT(seekpos, _IO_default_seekpos),

JUMP_INIT(setbuf, _IO_new_file_setbuf),

JUMP_INIT(sync, _IO_new_file_sync),

JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),

JUMP_INIT(read, INTUSE(_IO_file_read)),

JUMP_INIT(write, _IO_new_file_write),

JUMP_INIT(seek, INTUSE(_IO_file_seek)),

JUMP_INIT(close, INTUSE(_IO_file_close)),

JUMP_INIT(stat, INTUSE(_IO_file_stat)),

JUMP_INIT(showmanyc, _IO_default_showmanyc),

JUMP_INIT(imbue, _IO_default_imbue)

};

至于怎么跳转到这些函数,以及如何跳转到linux内核,由于涉及到glibc的一些细节,这里简单介绍一下进入内核后的情况:进入linux内核后,调用write(),在write之前所有的代码都是C库的代码,可以说是和平台无关的。而涉及到具体输出,就要调用操作系统提供给的接口。调用write()后,通过系统调用进入内核空间,首先是sys_write(),这个函数代码位于fs/read_write.c中。一进入sys_write(),就要根据传进来的fd描述符找到相应的file结构。对于标准输出,fd= 1,每个进程的进程控制块都有一个打开文件的数组files。file结构就是根据fd在这个数组中查找到相应的结构。找到结构后,就会调用file->write()来向外输出。具体输出到哪里,就要看file结构对应的设备驱动是什么。

通过本文可以理解:文件描述符0、1和2和stdout、stdin和stderr对应,如果要修改linux内核中文件描述符相关代码,一定要注意文件描述符0、1和2的分配和回收,否则会导致终端没有输出信息,也无法和内核输入信息。0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值