文件描述符(fd)
文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
什么是文件描述符?
进程利用文件描述符来访问文件。文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,进程就返回一个文件描述符。
每个linux进程都应该有三个标准的文件描述符,对应三个标准流。
fd(0)对应标准输入(stdin),对应的设备键盘(文件)。
fd(1)对应标准输出(stdout),对应的设备显示器(文件)。
fd(2)对应标准错误(stderror),对应的设备显示器(文件)。
文件描述符的分配是从当前未被使用的最小值分配。(如:再创建文件时,对应的fd为3,依次类推。如果关闭了0(close(0);)下一个打开文件的文件描述符为1)
在Linux中,每个进程会在进程控制块(task_struct)当中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表都有一个指向已经打开文件的指针。
文件指针与文件描述符的区别
什么是文件指针?
在C语言中,一个指针变量指向一个文件,则这个指针就是文件指针。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。
文件描述符是唯一的,但是文件指针不是唯一的,文件指针指向的对象是唯一的。文件描述符是文件描述符表的一个索引,因此从某些意义上来说,文件指针就是文件描述符的句柄。
FILE结构包含的字段及内容
C语言的stdio.h头文件中,定义了用于文件操作的结构体FILE
#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20 // 一次打开的最大文件数
// 定义FILE结构体
typedef struct _iobuf {
int cnt; // 剩余的字符,如果是输入缓冲区,那么就表示缓冲区中还有多少个字符未被读取
char *ptr; // 下一个要被读取的字符的地址
char *base; // 缓冲区基地址
int flag; // 读写状态标志位
int fd; // 文件描述符
} FILE;
extern FILE _iob[OPEN_MAX];
#define stdin (&_iob[0]) // stdin 的文件描述符为0
#define stdout (&_iob[1]) // stdout 的文件描述符为1
#define stderr (&_iob[2]) // stdout 的文件描述符为2
enum _flags {
_READ =01, // 读文件
_WRITE =02, // 写文件
_UNBUF =04, // 无缓冲
_EOF = 010, // 文件结尾EOF
_ERR = 020 // 出错
};
int _fillbuf(FILE *); // 函数声明,填充缓冲区
int _flushbuf(int, FILE *); // 函数声明,刷新缓冲区
#define feof(p) ((p)->flag & _EOF) != 0)
#define ferror(p) ((p)->flag & _ERR) != 0)
#define fileno(p) ((p)->fd)
#define getc(p) (--(p)->cnt >= 0 \
? (unsigned char) *(p)->ptr++ : _fillbuf(p))
#define putc(x,p) (--(p)->cnt >= 0 \
? *(p)->ptr++ = (x) : _flushbuf((x),p))
#define getchar() getc(stdin)
#define putcher(x) putc ((x), stdout)