标准I/O的缓存

标准I/O的缓存

概述

    标准 I / O库,它们的操作则是围绕流( s t r e a m)进⾏的 。当⽤标准I / O库打开或创建⼀个⽂件时,我们已使⼀个流与⼀个⽂件相结合。

    当打开⼀个流时,标准 I / O函数f o p e n返回⼀个指向F I L E对象的指针。该对象通常是⼀个结构,它包含了I / O库为管理该流所需要的所有信息:⽤于实际 I / O的⽂件描述符,指向流缓存的指针,缓存的⻓度,当前在缓存中的字符数,出错标志等等。

FILE 相关的声明与定义

__BEGIN_NAMESPACE_STD宏定义

文件:/usr/include/sys/cdefs.h

…

/* The standardlibrary needs the functions from the ISO C90 standard

   in the std namespace.  At the same time we want to be safe for

   future changes and we include the ISO C99code in the non-standard namespace __c99. The C++ wrapper header take case of adding the   definitions to the global namespace.  */

#ifdefined __cplusplus && defined _GLIBCPP_USE_NAMESPACES

# define__BEGIN_NAMESPACE_STD  namespace std {

# define__END_NAMESPACE_STD    }

# define__USING_NAMESPACE_STD(name) using std::name;

# define__BEGIN_NAMESPACE_C99  namespace __c99 {

# define__END_NAMESPACE_C99    }

# define__USING_NAMESPACE_C99(name) using __c99::name;

#else

/* Forcompatibility we do not add the declarations into any

   namespace. They will end up in the global namespace which is what old codeexpects.  */

# define__BEGIN_NAMESPACE_STD

# define__END_NAMESPACE_STD

# define__USING_NAMESPACE_STD(name)

# define__BEGIN_NAMESPACE_C99

# define__END_NAMESPACE_C99

# define__USING_NAMESPACE_C99(name)

#endif

…


FILE声明

文件:/usr/include/stdio.h

/* Define outsideof namespace so the C++ is happy.  */

struct_IO_FILE;

__BEGIN_NAMESPACE_STD

/* The opaque typeof streams.  This is the definition usedelsewhere.  */

typedefstruct _IO_FILE FILE;

__END_NAMESPACE_STD

/* The opaque typeof streams.  This is the definition usedelsewhere.  */

typedef struct_IO_FILE __FILE;

#include<libio.h>

struct _IO_FILE 定义

struct _IO_FILE {

  int _flags;           /* High-order word is _IO_MAGIC;rest is flags. */

#define_IO_file_flags _flags

 

  /* The following pointers correspond to theC++ 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 supportbacking up and undo. */

  char *_IO_save_base; /* Pointer to start ofnon-current get area. */

  char *_IO_backup_base;  /* Pointer to first valid character of backuparea */

  char *_IO_save_end; /* Pointer to end ofnon-current get area. */

 

  struct _IO_marker *_markers;

 

  struct _IO_FILE *_chain;

 

  int _fileno;

#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

};


打印有关缓存状态信息

测试代码

#include<stdio.h>

 

void    pr_stdio(const char *, FILE *);

int             is_unbuffered(FILE *);

int             is_linebuffered(FILE *);

int             buffer_size(FILE *);

 

int main(void)

{

        FILE   *fp;

 

        fputs("enter anycharacter\n", stdout);

        if (getchar() == EOF)

                printf("getcharerror");

        fputs("one line to standarderror\n", stderr);

 

        pr_stdio("stdin",  stdin);

        pr_stdio("stdout", stdout);

        pr_stdio("stderr", stderr);

 

        if ((fp =fopen("/etc/passwd", "r")) == NULL)

                printf("fopenerror");

        if (getc(fp) == EOF)

                printf("getc error");

        pr_stdio("/etc/passwd", fp);

        return 0;

}

 

void

pr_stdio(constchar *name, FILE *fp)

{

        printf("stream = %s, ",name);

        if (is_unbuffered(fp))

                printf("unbuffered");

        else if (is_linebuffered(fp))

                printf("linebuffered");

        else /* if neither of above */

                printf("fullybuffered");

        printf(", buffer size =%d\n", buffer_size(fp));

}

 

int  is_unbuffered(FILE *fp)

{

        return(fp->_flags &_IO_UNBUFFERED);

}

 

int is_linebuffered(FILE*fp)

{

        return(fp->_flags &_IO_LINE_BUF);

}

 

int buffer_size(FILE*fp)

{

        return(fp->_IO_buf_end -fp->_IO_buf_base);

}

程序输出

enter anycharacter

1

one line tostandard error

stream = stdin,line buffered, buffer size = 1024

stream = stdout,line buffered, buffer size = 1024

stream = stderr,unbuffered, buffer size = 1

stream =/etc/passwd, fully buffered, buffer size = 4096

代码说明

    当标准输⼊、输出连⾄终端时,它们是⾏缓存的,⾏缓存的⻓度是1024字节。

    当将这两个流重新定向到普通⽂件时,它们就变成是全缓存的,其缓存⻓度是该⽂件系统优先选⽤的 I / O⻓度,该系统的全缓存长度是4096。可参看https://blog.csdn.net/xiangguiwang/article/details/79733769 。


猜你喜欢

转载自blog.csdn.net/xiangguiwang/article/details/79778517