调用链

getchar()
	_IO_getc_unlocked
		__uflow
		_IO_default_uflow
			_IO_file_underflow (也叫做_IO_new_file_underflow)
				_IO_SYSREAD (fp, fp->_IO_buf_base,fp->_IO_buf_end - fp->_IO_buf_base); //关键函数

流程分析

这里分析只getchar一般流程首先getchar是调用了_IO_getc_unlocked

int
getchar (void)
{
  int result;
  if (!_IO_need_lock (stdin))
    return _IO_getc_unlocked (stdin);
  _IO_acquire_lock (stdin);
  result = _IO_getc_unlocked (stdin);
  _IO_release_lock (stdin);
  return result;
}

调用__uflow

_IO_getc_unlocked 然后宏定义如下调用了__uflow

#define _IO_getc_unlocked(_fp) __getc_unlocked_body (_fp)
#define __getc_unlocked_body(_fp)					\\
  (__glibc_unlikely ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end)	\\
   ? __uflow (_fp) : *(unsigned char *) (_fp)->_IO_read_ptr++)

调用__uflow 此时通过调试fd的情况如下指向的是*IO_2_1_stdin*

Untitled

*IO_2_1_stdin 此时情况如下*

Untitled

通过观察发现常规调用getchar时此时fd不满足下面if条件的任何一种情况

int
__uflow (FILE *fp)
{
  if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
    return EOF;

  if (fp->_mode == 0)
    _IO_fwide (fp, -1);
  if (_IO_in_put_mode (fp))
    if (_IO_switch_to_get_mode (fp) == EOF)
      return EOF;
  if (fp->_IO_read_ptr < fp->_IO_read_end)
    return *(unsigned char *) fp->_IO_read_ptr++;
  if (_IO_in_backup (fp))
    {
      _IO_switch_to_main_get_area (fp);
      if (fp->_IO_read_ptr < fp->_IO_read_end)
	return *(unsigned char *) fp->_IO_read_ptr++;
    }
  if (_IO_have_markers (fp))
    {
      if (save_for_backup (fp, fp->_IO_read_end))
	return EOF;
    }
  else if (_IO_have_backup (fp))
    _IO_free_backup_area (fp);
  return _IO_UFLOW (fp);
}

调用_IO_default_uflow

然后程序就在__uflow函数中跳转到_IO_default_uflow

int
_IO_default_uflow (FILE *fp)
{
  int ch = _IO_UNDERFLOW (fp);
  if (ch == EOF)
    return EOF;
  return *(unsigned char *) fp->_IO_read_ptr++;
}

然后在该函数中调用_IO_UNDERFLOW ,该函数是一个虚表函数,对应JUMP0 (__underflow, FP)

#define _IO_UNDERFLOW(FP) JUMP0 (__underflow, FP)
#define JUMP0(FUNC, THIS) (_IO_JUMPS_FUNC(THIS)->FUNC) (THIS)

而此时fp指向的*IO_2_1_stdin* 他的vtable表指向_IO_file_jumps