Linux下 文件描述符(fd)与 文件指针(FILE*)

一、文件描述符(fd)

我们都知道在Linux下一切皆文件。当然设备也不例外,如果要对某个设备进行操作,就不得不打开此设备文件,打开文件就会获得该文件的文件描述符fd( file discriptor), 它就是一个很小的整数,每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。

Linux下 文件描述符(fd)与 文件指针(FILE*)

图中文件描述符即为文件描述符数组的下标

文件描述符的分配规律:从当前未使用的最小的整数开始分配;

文件描述符的缺点:

不能移植到UNIX以外的系统上去,也不直观。

举一个系统函数的例子:ssize_t write ( int fd, const void *buf, size_t count);

write: 是系统写函数 fd: 文件描述符 (一个整数) *buf: 内容写在哪里 count: 一次写多少个;

概括:

每一个进程在PCB(Process Control Block)即进程控制块中都保存着一分文件描述符表,文件描述符就是这个表的索引,文件描述符表中每个表项都有一个指向已打开文件的指针。现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体

fd详解

fd:为打开文件的文件描述符,而每个进程都有一张文件描述符表,fd文件描述符就是这张表的索引,同样这张表中有一表项,该表项又是指向前面提到打开文件的file结构体,file结构体才是内核中用来描述文件属性的结构体。

FILE结构体

1、FILE结构体中的成员

缓冲区基址,缓冲区当前指针,缓冲区大小,缓冲区剩余字节数,文件读写方式等。

struct FILE

{

char *_ptr;//文件输入的下一个位置

int _cnt;//当前缓冲区的相对位置

char *_base;//指基础位置(文件的起始位置)

int _flag;//文件标志

int _file;//文件的有效性验证

int _charbuf;//检查缓冲区状况,如果缓冲区则不读取

int _bufsiz;//文件的大小

char *_tmpfname;//临时文件名

};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2、(FILE*)文件指针

文件指针指向进程用户区中一个被叫做FILE结构的结构数据。FILE结构包括一个缓冲区一个文件描述符 。而文件描述符是文件描述符表的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上,文件描述符被称作文件句柄)。

通常,任何程序运行起来之后都会默认的打开三个标准输入流(stdin:键盘),标准输出流(stdout:显示器),标准错误流(stderr:显示器)。

文件描述符与文件指针的区别

简单归纳:fd只是一个整数,在open时产生,起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针file。

open:文件描述符的操作(如:open)返回的是一个文件描述符(int fd),内核会在每个进程空间中维护一个文件描述符表,所有打开的文件都将通过,此表中的文件描述符来引用。

fopen:流(如:fopen)返回的是一个文件指针(即指向FILE结构体的指针),FILE结构是包含有文件描述符的,fopen可以看做是open(fd直接操作的系统调用)的封装,它的优点是带有I/O缓存。

C语言的文件指针与文件描述符的相互转换可通过fdopen和fileno两个函数实现。它们都包含在头文件stdio.h中。

fdopen的原型:

FILE *fdopen(int filedes,const char *opentype);

  • 1

第一个参数filedes是一个打开的文件描述符,opentype是表示打开方式的字符串,和fopen函数具有相同的取值,比如”w”或”w+”等。但是你必须保证该字符串的描述和文件实际的打开方式是匹配的。函数fopen()就是返回打开文件的指针;如果操作失败,返回空指针null。

把文件流指针转换成文件描述符用fileno函数,

其原型为:

int fileno(FILE *stream);

  • 1

它返回的是和stream文件流对应的文件描述符。如果失败,返回-1;

当程序执行时,就已经有三个标准文件流打开了,它们分别是(标准输入)stdin,(标准输出)stdout,(标准错误输出)stderr,和流式文件相对应的是,也有三个文件描述符被预先占用(它们分别是:

0((标准输入)stdin),1((标准输出)stdout),2((标准错误输)stderr));

相关推荐