在vs2008下使用cygwin(23):stdin,stdout和stderr

 

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

   

本文适用于

Cygwin-1.16

Vs2008

   

欢迎转载,但请保留作者信息

 

stdinstdoutstderr3个标准的输入输出流,在vc中定义了,同样在cygwin中也定义了,但是由于cygwinvc所使用的FILE结构的不同,对它们做了重命名处理:

#define  cyg_stdin (_REENT->_stdin)

#define  cyg_stdout    (_REENT->_stdout)

#define  cyg_stderr    (_REENT->_stderr)

在这里_REENT将指向一个全局变量,这个全局变量使用了TLS,因而是线程安全的。

CYG_API  struct _reent * __getreent (void);

# define _REENT (__getreent())

_reent这个结构体中,定义了stdinstdoutstderr三个FILE指针:

/*

 * struct _reent

 *

 * This structure contains *all* globals needed by the library.

 * It's raison d'etre is to facilitate threads by making all library routines

 * reentrant.  IE: All state information is contained here.

 */

 

struct _reent

{

  int _errno;          /* local copy of errno */

 

  /* CYG_FILE is a big struct and may change over time.  To try to achieve binary

     compatibility with future versions, put cyg_stdin,cyg_stdout,cyg_stderr here.

     These are pointers into member __sf defined below.  */

  __FILE *_stdin, *_stdout, *_stderr;

……………………..

 

  /* These are here last so that __FILE can grow without changing the offsets

     of the above members (on the off chance that future binary compatibility

     would be broken otherwise).  */

  struct _glue __sglue;     /* root of glue chain */

  __FILE __sf[3];           /* first three file descriptors */

};

当需要使用putcprintf之类的函数的时候,这些函数将检查这个结构体是否已经初始化,如果没有则进行一次初始化操作:

int

_DEFUN(cyg_putc, (c, fp),

       int c _AND

       register CYG_FILE *fp)

{

#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)

  int result;

  CHECK_INIT (_REENT, fp);

  _flockfile (fp);

  result = __sputc_r (_REENT, c, fp);

  _funlockfile (fp);

  return result;

#else

  return _putc_r (_REENT, c, fp);

#endif

}

初始化过程由CHECK_INIT这个宏来控制,它的定义如下:

#define CHECK_INIT(ptr, fp) /

  do                        /

    {                            /

      if ((ptr) && !(ptr)->__sdidinit)         /

     __sinit (ptr);                   /

    }                            /

  while (0)

也就是说,它将调用__sinit函数来实际完成初始化工作:

/*

 * __sinit() is called whenever stdio's internal variables must be set up.

 */

 

_VOID

_DEFUN(__sinit, (s),

       struct _reent *s)

{

  __sinit_lock_acquire ();

 

  if (s->__sdidinit)

    {

      __sinit_lock_release ();

      return;

    }

 

  /* make sure we clean up on exit */

  s->__cleanup = _cleanup_r;     /* conservative */

  s->__sdidinit = 1;

 

  s->__sglue._next = NULL;

#ifndef _REENT_SMALL

  s->__sglue._niobs = 3;

  s->__sglue._iobs = &s->__sf[0];

#else

  s->__sglue._niobs = 0;

  s->__sglue._iobs = NULL;

  s->_stdin = __sfp(s);

  s->_stdout = __sfp(s);

  s->_stderr = __sfp(s);

#endif

 

  std (s->_stdin,  __SRD, 0, s);

 

  /* On platforms that have true file system I/O, we can verify

     whether cyg_stdout is an interactive terminal or not, as part of

     __smakebuf on first use of the stream.  For all other platforms,

     we will default to line buffered mode here.  Technically, POSIX

     requires both cyg_stdin and cyg_stdout to be line-buffered, but tradition

     leaves cyg_stdin alone on systems without fcntl.  */

#ifdef HAVE_FCNTL

  std (s->_stdout, __SWR, 1, s);

#else

  std (s->_stdout, __SWR | __SLBF, 1, s);

#endif

 

  /* POSIX requires cyg_stderr to be opened for reading and writing, even

     when the underlying fd 2 is write-only.  */

  std (s->_stderr, __SRW | __SNBF, 2, s);

 

  __sinit_lock_release ();

}

从这里可以看出_stdin_stdout_stderr这三个成员是由std函数来初始化的,这个函数定义如下:

static _VOID

_DEFUN(std, (ptr, flags, file, data),

            CYG_FILE *ptr _AND

            int flags _AND

            int file  _AND

            struct _reent *data)

{

  ptr->_p = 0;

  ptr->_r = 0;

  ptr->_w = 0;

  ptr->_flags = flags;

  ptr->_file = file;

  ptr->_bf._base = 0;

  ptr->_bf._size = 0;

  ptr->_lbfsize = 0;

  ptr->_cookie = ptr;

  ptr->_read = __sread;

#ifndef __LARGE64_FILES

  ptr->_write = __swrite;

#else /* __LARGE64_FILES */

  ptr->_write = __swrite64;

  ptr->_seek64 = __sseek64;

  ptr->_flags |= __SL64;

#endif /* __LARGE64_FILES */

  ptr->_seek = __sseek;

  ptr->_close = __sclose;

#if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL)

  __lock_init_recursive (ptr->_lock);

  /*

   * #else

   * lock is already initialized in __sfp

   */

#endif

 

#ifdef __SCLE

  if (__stextmode (ptr->_file))

    ptr->_flags |= __SCLE;

#endif

}

注意到调用时的第三个参数file,分别使用的是012。这三个值分别是windows对于标准输入,标准输出和标准错误的文件号。从这里可以看出,cygwin仅是使用一个FILE结构体对这三个windows提供的标准文件进行了封装,所有的操作最终将使用这三个文件号调用windows的系统服务完成。

 

 

 

参考资料

vs2008下使用cygwin1):前言( 2008-10-16 )

vs2008下使用cygwin2):i686-pc-cygwin/newlib/Makefile分析( 2008-10-16 )

vs2008下使用cygwin3):i686-pc-cygwin/newlib/libc/Makefile分析( 2008-10-16 )

vs2008下使用cygwin4):i686-pc-cygwin/newlib/libc/argz/Makefile分析( 2008-10-16 )

vs2008下使用cygwin5):i686-pc-cygwin/newlib/libc/stdlib/Makefile分析( 2008-10-16 )

vs2008下使用cygwin6):i686-pc-cygwin/newlib/libc/ctype/Makefile分析( 2008-10-16 )

vs2008下使用cygwin7):i686-pc-cygwin/newlib/libc/search/Makefile分析( 2008-10-16 )

vs2008下使用cygwin8):i686-pc-cygwin/newlib/libc/stdio/Makefile分析( 2008-10-16 )

vs2008使用cygwin9):i686-pc-cygwin/newlib/libc/stdio64/Makefile分析( 2008-10-16 )

vs2008下使用cygwin10):i686-pc-cygwin/newlib/libc/string/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin11):i686-pc-cygwin/newlib/libc/signal/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin12):i686-pc-cygwin/newlib/libc/time/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin13):i686-pc-cygwin/newlib/libc/locale/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin14):i686-pc-cygwin/newlib/libc/reent/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin15):i686-pc-cygwin/newlib/libc/misc/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin16):i686-pc-cygwin/newlib/libc/machine/i386/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin17):i686-pc-cygwin/newlib/libc/posix/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin18):i686-pc-cygwin/newlib/libc/syscalls/Makefile分析 ( 2008-10-16 )

vs2008下使用cygwin19):i686-pc-cygwin/newlib/libm/Makefile分析( 2008-10-17 )

vs2008下使用cygwin20):i686-pc-cygwin/newlib/libm/math/Makefile分析 2008-10-17

vs2008下使用cygwin21):i686-pc-cygwin/newlib/libm/common/Makefile分析( 2008-10-17 )

vs2008下使用cygwin22):使用tls( 2008-10-20 )

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值