文件描述符的目的是什么?

时间:2019-02-07 02:29:08

标签: c fopen file-descriptor

我的理解是fopen()open()都可以用来打开文件。 open()返回文件描述符。但是就获取用于写入或读取的文件而言,它们应该等效。定义文件描述符的目的是什么?从Wiki页面尚不清楚。

https://en.wikipedia.org/wiki/File_descriptor

2 个答案:

答案 0 :(得分:2)

fopen返回一个FILE *,它是文件描述符的包装器(我将忽略此处的“规范未要求的内容”,因为我不知道有一个实现不这样做)。从高层次看,它是这样的:

application --FILE *--> libc --file descriptor--> kernel

Shell直接在文件描述符上操作,主要是因为它们正在执行其他程序,并且您不能修改其他程序的FILE *对象。但是,您可以在启动时使用dup系统调用来修改其他程序的文件描述符(即,在forkexec之间)。例如:

/bin/cat > foo.txt

这告诉外壳程序执行/bin/cat程序,但首先将stdout(文件描述符#1)重定向到它打开的文件。这是通过(伪代码)实现的:

if (fork() == 0) {
    int fd = open("foo.txt");
    dup2(fd, 1);
    exec("/bin/cat");
}

您可以使用FILE *进行的最接近的操作是调用freopen,但是与文件描述符不同,使用exec时不会持久。

但是,如果它只是文件描述符的包装器,那为什么还需要FILE *?一个主要好处是拥有预读缓冲区。例如,考虑fgets。这最终将在与您传入的read关联的文件描述符上调用FILE *系统调用。但是它如何知道要读取多少内容?内核没有选择说“给我一行”(撇开行缓冲的ttys)。如果您在前read的第一行中读了多行,那么下次调用fgets时,您可能只会得到下一行的一部分,因为内核已经在上一个{ {1}}系统调用。另一种选择是一次调用read一个字符,这对于性能来说是可怕的。

那么libc做什么?它一次读取一堆字符,然后将多余的字符存储在read对象的内部缓冲区中。下次调用FILE *时,它可以使用内部缓冲区。此缓冲区还与fgets之类的功能共享,因此您可以交错调用freadfgets而不丢失数据。

答案 1 :(得分:0)

这两个功能处于不同的级别:

  • open()是用于打开文件的下层POSIX函数。它返回一个不同的整数以标识并允许访问打开的文件。该整数是文件描述符。
  • fopen()是打开文件的高级可移植C标准库函数。

在POSIX系统上,可移植的fopen()可能会调用不可移植的open(),但这是一个实现细节。

如有疑问,请选择fopen()

有关更多信息,在Linux系统上,man 2 read。 POSIX read()函数通过open()返回的文件描述符读取数据。

相关问题