文件:可以看做字节的序列。所有的 I/O 设备也是用文件来表示
文件类型:
- 普通文件:
文本文件(文本文件只包含 ASCII 或 Unicode 字符)和二进制文件 - 目录:
相关一组文件的索引,包含一个以树状结构组织的链接(link)数组,并且每个目录至少包含两条记录(当前目录和上一层目录)。通过绝对/相对路径名来指定位置。 - 套接字:和另一台机器上的进程通信的类型
结合『所有东西都是文件』这个抽象,无论是输入输出重定向,挂载不同的设备,网络编程,都可以由系统输入输出这个统一的模型来进行描述。
Linux内核引用Unix I/O统一输入输出的方式:
- 打开/创建文件
int open(char* filename,int flages,mode_t mode);
//返回值为文件描述符
/*由 Linux shell(注:感谢网友 yybear 的勘误) 创建的进程都会默认打开三个文件*/
内核通过以下3个数据结构表示打开的文件:
1.描述符表:每个进程都有
2.文件表:进程共享。包含文件位置,引用计数和指向v-node表的指针
3.v-node表:进程共享。包含stat结构(元数据:通过内核维护的描述文件的数据CP632~CP633)
重定向:
int dup2(int oldfd,int newfd);
//oldfd和newfd为描述符表项
//用oldfd覆盖newfd
//之后写到文件A的数据将被重定向到文件B
- 读文件
ssize_t read(int fd,void *buf,size_t n);
//从fd复制n个字节到内存位置buf
//返回(真正)读取的字节数量
//short cut CP626
- 写文件
ssize_t read(int fd,const void *buf,size_t n);
- 关闭文件
int close(int fd);
//不能重复关闭
标准I/O
作为Unix I/O的高级替代,尽量减少系统调用的次数(开销较大)。例如先调用read函数填充流缓冲区,再利用标准I/O按要求进行读取。
将文件视为流
流:文件描述符和缓冲区在内存中的抽象,指向文件类型的指针
程序开始时默认打开3个流
#include <stdio.h>
extern FILE *stdin; // 标准输入
extern FILE *stdout; // 标准输出
extern FILE *stderr; // 标准错误