首页 > 代码库 > Linux环境编程之文件I/O(一):文件描述符

Linux环境编程之文件I/O(一):文件描述符

(一)

首先,对于内核来讲,它是利用“文件描述符”来访问文件的。文件描述符一般是一个非负的整数。当我们用open打开已有的文件或者用creat创建新的文件时,都会返回一个文件描述符。有了文件描述符之后,我们就可以利用该文件描述进行文件的读写,即read、write系统调用都需要文件描述符fd(file descriptor)作为其参数。从以上描述可以看出,当我们想要用read、write等系统调用对文件进行读写等操作之前,必须用open或creat系统调用得到文件的描述符。


一般Unix系统中shell使用文件描述符0与进程的标注输入相关联,文件描述符1与进程的输出相关联,文件描述符2与标注错误相关联。在应用程序中,一般用0、1、2代替常量STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。这些代替都定义在</usr/include/unistd.h>头文件中:

/*standard file descriptors*/

#define STDIN_FILENO 0              /*input*/

#define STDOUT_FILENO 1         /*output*/

#define STDERR_FILENO 2       /*error output*/

示例程序如下:

/*demo.c*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int
main(void)
{
	int fd;
        /*打开文件test.c,由于不存在,所以打开失败,返回-1*/
	fd = open("test.c", O_RDONLY);
	printf("fd = %d.\n",fd);
        /*创建文件,因为描述符0、1、2属于默认,所以创建的该描述符为3*/
	fd = creat("test.c", O_RDWR);
	printf("fd = %d.\n",fd);
	return 0;
}

编译执行:
gcc demo.c
./a.out
结果显示:
fd = -1.
fd = 3.


(二)

每个进程在Linux内核中都有一个task_struct结构体来维护进程的相关信息,称为进程描述符。进程描述符task_struct中有个指针成员(struct files_styruct *files)指向files_struct结构体,称为文件描述符表,其中的每个表项包含一个指向已打开的文件的指针。

用户不能直接访问内核中的文件描述符表,而只能使用文件描述符表的索引,即文件描述符。


(三)

文件描述符、文件指针、文件路径三者有联系也有区别,开始学习时很难理清三者的关系。

首先,文件描述符fd一般是在Unix系统或类Unix系统中的概念,它其实是一个整数,用它可以来获取文件描述符表中的某个已打开文件。

文件指针FILE是C库中的概念,它不单单在Linux系统中,在windows中也会出现,文件指针指向进程中用户区中一个被称为FILE结构的数据结构,该FILE结构包括一个缓冲区和一个文件描述符。FILE中包含fd信息,还包含IO缓冲,所以FILE比fd更适合跨平台。它们之间可以利用fdopen函数和fileno函数互相转化。

FILE *fdopen(int fd, const char *mode);

int fileno(FILE *stream);

文件路径就是文件所在路径,通常,我们就是通过文件路径得到具体文件,从而得到文件描述符、文件指针的。