文件描述符

March 4, 2025

抽象表述

<p>文件描述符是一个非零整数</p>

在操作系统中去让机器认识:(不同的)文件、socket、外部 I/O 资源等等是不简单的事情,但是机器认识数字,那我们就可以利用这个特性,抽象的描述以上的这些资源,因此文件描述符 就是来表述资源的,为了不打乱资源的使用,系统中对有着一张全局的 、而每个进程也有自己的 。当进程打开一个文件时,操作系统在全局文件描述符表和进程文件描述符表中都会有一个对应的条目,它们保持同步。

通俗来说,每个进程在启动时都会自动打开三个标准文件描述符:

  • 文件描述符0(stdin):标准输入,通常是键盘输入。
  • 文件描述符1(stdout):标准输出,通常是屏幕上的文本输出。
  • 文件描述符 2(stderr):标准错误输出,通常也是屏幕上的文本输出,但通常用于显示错误消息。 而在之后的操作中:进程打开或创建一个文件时,操作系统就为这个文件标识一个文件描述符,它写入表中作为其中的一个索引,为接下来的 read 和 write 作准备。

使用

既然文件描述符是操作系统提供的一种资源抽象,那它就可以允许(系统)程序通过一个数字来访问文件和 I/O 资源,而无需关心机器底层的具体实现细节。

在 Unix/类 Unix 的系统中调用 read() 和 write() 从文件描述符所指的文件中读或者写 n 个字节,如:

char buf[512];

n = read(0, buf, sizeof(buf));

n = write(1, buf, sizeof(buf));

而且它们的返回的是实际读或写的字节数,那么 n 小于 0 的时候就发生了错误。

那么这就有新的问题了,我这里用的是标准输入和标准输出,之前说了,当文件打开或创建的时候有标识文件描述符,而且系统是按顺序来标识的,直到最大(),也就是说,有新文件打开,它文件描述符是 3 那么我怎么用 read 和 write 对 3 操作,这里就有一个 Unix 伟大的设计了— I/O 重定向

// cat < input.txt
char *argv[2];
argv[0] = "cat";
### argv[1] = 0;
if(fork() == 0) {
    close(0);
    open("input.txt", O_RDONLY);
    exec("cat", argv);
}

以上的操作是:fork 一个子进程(它有父进程的表和一切),用 close 把标准输入关闭,用 open 打开新文件 — input.txt ,系统是顺序标识的,所以 input.txt 在子进程中是 0cat 是指向标准输入的,即,代码将 input.txt 输入到 cat,再输出到 shell 中。

最后更新于