FILE文件指针

C语言中使用文件指针做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。

FILE结构包括缓冲区和文件描述符。而文件描述符是文件描述符表的一个索引,也就是说c语言的文件指针是 Linux 系统中对文件描述符的一种封装 。

下面看FILE结构体里面都有那些成员

上面是文件指针指向的结构体,可以发现文件指针结构体里包含有文件描述符,说明文件指针是对文件描述符的一种封装。文件指针是C语言库里的提供的一个结构体,文件描述符是系统调用接口;

为什么系统已经有了文件描述符,库里面还要对其做一层封装呢?

  1. 方便程序员使用;

  2. 可以提高程序的移植性。

FILE结构体里面还有缓冲区:

  1. 将数据写入硬盘文件中时,缓冲区的刷新方式默认为全缓冲,

  2. 将数据写入显示文件中,缓冲区的刷新方式默认为行缓冲;

而系统调用的函数write()写入时,是没有缓冲的。

文件描述符

文件描述符:在Linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针,已打开的文件在内核中用file结构体(注意不是FILE结构体)表示,文件描述符表中的指针指向file结构体。

下面看文件file结构体

标准输入(stdin)的文件描述符是 0

标准输出(stdout)的文件描述符是 1

标准错误(stderr)的文件描述符是 2

文件描述符的分配规则:从当前未被分配的最小整数处分匹配。

shell 和很多应用程序都使用这种习惯,因此,如果内核不遵循这种习惯的话,很多应用程序将不能使用。

POSIX 定义了 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 来代替 0、1、2。这三个符号常量的定义位于头文件 unistd.h。

文件描述符的有效范围是 0 到 OPEN_MAX。每个进程最多可以打开文件的多少取决于系统内存的大小,int的大小,以及系统管理员设定的限制。Linux 2.4.22 强制规定最多不能超过 1,048,576。

文件描述符的两大缺点 :

  1. 在非UNIX / Linux操作系统上(如Windows NT),无法基于这一概念进行编程。

  2. 由于文件描述符在形式上不过是个整数,当代码量增大时,会使编程者难以分清哪些整数意味着数据,那些意味着文件描述符。因此,完成的代码可读性也就会变得很差。

FILE *中除了包含了fd信息,还包含了IO缓冲,是C标准形式,所以FILE *比fd更适合跨平台,应该多用fopen在,少用open。

文件指针与文件描述符的转换

这要通过fdopen和fileno两个函数实现。它们都包含在头文件stdio.h中。

把文件描述符转换成文件流指针用fdopen函数,其原型为:

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

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

把文件流指针转换成文件描述符用fileno函数,其原型为:

int fileno(FILE *stream);

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

当程序执行时,就已经有三个文件流打开了,它们分别是标准输入stdin,标准输出stdout和标准错误输出stderr。和流式文件相对应的是,也有三个文件描述符被预先打开,它们分别是0,1,2,代表标准输入、标准输出和标准错误输出。

转载:http://blog.csdn.net/sunjiangangok/article/details/69943620