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

标签 c fopen file-descriptor

<分区>

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

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

最佳答案

fopen 返回一个 FILE * ,它是文件描述符的包装器(我将在这里忽略“这不是规范所要求的”方面,就像我一样不知道不执行此操作的实现)。在高层次上,它看起来像这样:

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

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

/bin/cat > foo.txt

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

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

您可以使用 FILE * 做的最接近的事情是调用 freopen,但与文件描述符不同,当使用 exec 时,这不会持久化。

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

那么 libc 是做什么的呢?它一次读取一堆字符,然后将多余的字符存储在 FILE * 对象的内部缓冲区中。下次您调用 fgets 时,它就可以使用内部缓冲区。此缓冲区还与 fread 等函数共享,因此您可以交替调用 fgetsfread 而不会丢失数据。

关于c - 文件描述符的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54565453/

相关文章:

Calloc 导致段错误

php - 无法打开流 : No such file of directory in. .. PHP fopen

C 重定向终端描述符

c - 内部文件?系统调用读写

c - connect() C 函数无法连接我的路由器,但我可以使用 javascript ajax 调用连接它

c - 在 c 中按星期几分组列表

C char* 指针指向它们绝对不应该指向的相同位置

c - MSDN 对 fopen(或 fopen_s)的警告想表达什么?

c - 理解指针算术

linux - 为什么 mplayer 在循环时退出 Bash?