Linux 系统编程中一切资源皆文件。文件概念(内容与属性),对比 C 标准库文件接口与系统调用接口(open/close/read/write)。阐述文件描述符分配规则及标准流(stdin/stdout/stderr)机制,介绍重定向原理及 dup2 函数用法。深入分析缓冲区机制(行缓冲/全缓冲/无缓冲),解释用户态与内核态数据拷贝流程,并通过 fork 示例说明缓冲区刷新时机对程序输出的影响。
kaikai6.6K 浏览
一、理解文件
1.1、文件的概念
文件存储在磁盘上。(狭义)
Linux 中一切皆文件,即把所有需要交互的资源全部抽象成为文件:普通文件,目录文件,设备文件,管道文件...。(广义)
1.2、文件的认知
文件 = 内容 + 属性。
内容:文件存储的数据,如文本中的文字,程序二进制代码。
属性:文件的信息,包括文件名、大小、创建时间、权限、所有者等。
对于 0KB 的文件,即没有任何内容,但由于属性数据,所以占磁盘空间。
从系统角度看:对文件的操作其实是进程对文件的操作。
二、回顾 C 文件
2.1、C 文件接口
FILE *fopen(constchar *path, constchar *mode); // 写文件 int fputc(int character,FILE* stream); int fputs(const char *s, FILE *stream); int fprintf(FILE *stream, const char *format, ...); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); // 读文件 int fgetc(FILE* stream); char *fgets ( char *str, int num, FILE * stream ); int fscanf(FILE* stream, const char* format, ...); size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); int fclose(FILE *stream);
// 在/usr/include/stdio.htypedefstruct _IO_FILEFILE;// 在/usr/include/libio.hstruct _IO_FILE {int _flags; /* High-order word is _IO_MAGIC; rest is flags.*/#define _IO_file_flags _flags //缓冲区相关/* The following pointers correspond to the C++ 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 support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的文件描述符#if 0int _blksize;
#elseint _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. */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
};