与维基百科相比,什么样的文件描述符描述更简单?为什么需要它们?比如说,以壳进程为例,它是如何应用的呢? 进程表是否包含多个文件描述符?如果是,为什么?


当前回答

其他答案补充了很好的内容。我只是说说我的看法。

根据维基百科,我们可以肯定地知道:文件描述符是非负整数。我认为最重要的一点是:

文件描述符绑定到进程ID。

我们知道最著名的文件描述符是0、1和2。 0对应STDIN, 1对应STDOUT, 2对应STDERR。

比如说,以壳进程为例,它是如何应用的呢?

检查这段代码

#>sleep 1000 &
[12] 14726

我们创建了一个id为14726 (PID)的进程。 使用lsof -p 14726,我们可以得到这样的东西:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
sleep   14726 root  cwd    DIR    8,1     4096 1201140 /home/x
sleep   14726 root  rtd    DIR    8,1     4096       2 /
sleep   14726 root  txt    REG    8,1    35000  786587 /bin/sleep
sleep   14726 root  mem    REG    8,1 11864720 1186503 /usr/lib/locale/locale-archive
sleep   14726 root  mem    REG    8,1  2030544  137184 /lib/x86_64-linux-gnu/libc-2.27.so
sleep   14726 root  mem    REG    8,1   170960  137156 /lib/x86_64-linux-gnu/ld-2.27.so
sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

第4列FD和下一列TYPE对应于文件描述符和文件描述符类型。

FD的一些值可以是:

cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device

但是真正的文件描述符在下面:

NUMBER – Represent the actual file descriptor. 

数字后面的字符,即“1u”,表示文件打开的模式。R代表读,w代表写,u代表读和写。

TYPE文件类型。TYPEs的一些值是:

REG – Regular File
DIR – Directory
FIFO – First In First Out

但是所有的文件描述符都是 CHR—字符特殊文件(或字符设备文件)

现在,我们可以使用lsof -p PID轻松识别STDIN, STDOUT和STDERR的文件描述符,或者如果我们使用ls /proc/PID/fd.也可以看到同样的情况

还要注意,内核所跟踪的文件描述符表与文件表或inodes表并不相同。正如其他一些答案解释的那样,这些是独立的。

例如,您可能会问自己这些文件描述符的物理位置,以及在/dev/pts/6中存储了什么

sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

/dev/pts/6纯粹存在于内存中。这些不是常规文件,而是所谓的字符设备文件。你可以用:ls -l /dev/pts/6检查,它们将以c开头,在我的例子中是crw—w----。

回想一下大多数Linux之类的操作系统定义了七种类型的文件:

常规文件 目录 字符设备文件 块设备文件 本地域套接字 命名管道(fifo)和 符号链接

其他回答

来自马的嘴:APUE(理查德·史蒂文斯饰)。 对于内核,所有打开的文件都由文件描述符引用。文件描述符是非负数。

当我们打开一个现有文件或创建一个新文件时,内核会向进程返回一个文件描述符。内核维护一个包含所有正在使用的打开的文件描述符的表。文件描述符的分配通常是顺序的,它们从空闲文件描述符池中作为下一个空闲文件描述符分配给文件。关闭文件时,文件描述符将被释放,并可用于进一步分配。 请看这张图片了解更多细节:

When we want to read or write a file, we identify the file with the file descriptor that was returned by open() or create() function call, and use it as an argument to either read() or write(). It is by convention that, UNIX System shells associates the file descriptor 0 with Standard Input of a process, file descriptor 1 with Standard Output, and file descriptor 2 with Standard Error. File descriptor ranges from 0 to OPEN_MAX. File descriptor max value can be obtained with ulimit -n. For more information, go through 3rd chapter of APUE Book.

文件描述符(FD):

In Linux/Unix, everything is a file. Regular file, Directories, and even Devices are files. Every File has an associated number called File Descriptor (FD). Your screen also has a File Descriptor. When a program is executed the output is sent to File Descriptor of the screen, and you see program output on your monitor. If the output is sent to File Descriptor of the printer, the program output would have been printed. Error Redirection : Whenever you execute a program/command at the terminal, 3 files are always open standard input standard output standard error. These files are always present whenever a program is run. As explained before a file descriptor, is associated with each of these files. File                                        File Descriptor Standard Input STDIN              0 Standard Output STDOUT       1 Standard Error STDERR          2 For instance, while searching for files, one typically gets permission denied errors or some other kind of errors. These errors can be saved to a particular file. Example 1

$ ls mydir 2>错误文件.txt

标准错误的文件描述符是2。 如果没有任何名为mydir的目录,则命令的输出将保存到文件errorfile.txt 使用"2>"将错误输出重定向到名为"errorfile.txt"的文件 因此,程序输出不会充满错误。 我希望你得到了答案。

其他答案补充了很好的内容。我只是说说我的看法。

根据维基百科,我们可以肯定地知道:文件描述符是非负整数。我认为最重要的一点是:

文件描述符绑定到进程ID。

我们知道最著名的文件描述符是0、1和2。 0对应STDIN, 1对应STDOUT, 2对应STDERR。

比如说,以壳进程为例,它是如何应用的呢?

检查这段代码

#>sleep 1000 &
[12] 14726

我们创建了一个id为14726 (PID)的进程。 使用lsof -p 14726,我们可以得到这样的东西:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
sleep   14726 root  cwd    DIR    8,1     4096 1201140 /home/x
sleep   14726 root  rtd    DIR    8,1     4096       2 /
sleep   14726 root  txt    REG    8,1    35000  786587 /bin/sleep
sleep   14726 root  mem    REG    8,1 11864720 1186503 /usr/lib/locale/locale-archive
sleep   14726 root  mem    REG    8,1  2030544  137184 /lib/x86_64-linux-gnu/libc-2.27.so
sleep   14726 root  mem    REG    8,1   170960  137156 /lib/x86_64-linux-gnu/ld-2.27.so
sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

第4列FD和下一列TYPE对应于文件描述符和文件描述符类型。

FD的一些值可以是:

cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device

但是真正的文件描述符在下面:

NUMBER – Represent the actual file descriptor. 

数字后面的字符,即“1u”,表示文件打开的模式。R代表读,w代表写,u代表读和写。

TYPE文件类型。TYPEs的一些值是:

REG – Regular File
DIR – Directory
FIFO – First In First Out

但是所有的文件描述符都是 CHR—字符特殊文件(或字符设备文件)

现在,我们可以使用lsof -p PID轻松识别STDIN, STDOUT和STDERR的文件描述符,或者如果我们使用ls /proc/PID/fd.也可以看到同样的情况

还要注意,内核所跟踪的文件描述符表与文件表或inodes表并不相同。正如其他一些答案解释的那样,这些是独立的。

例如,您可能会问自己这些文件描述符的物理位置,以及在/dev/pts/6中存储了什么

sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

/dev/pts/6纯粹存在于内存中。这些不是常规文件,而是所谓的字符设备文件。你可以用:ls -l /dev/pts/6检查,它们将以c开头,在我的例子中是crw—w----。

回想一下大多数Linux之类的操作系统定义了七种类型的文件:

常规文件 目录 字符设备文件 块设备文件 本地域套接字 命名管道(fifo)和 符号链接

文件描述符

To Kernel all open files are referred to by file descriptors. A file descriptor is a non - negative integer. When we open an existing or create a new file, the kernel returns a file descriptor to a process. When we want to read or write on a file, we identify the file with file descriptor that was retuned by open or create, as an argument to either read or write. Each UNIX process has 20 file descriptors and it disposal, numbered 0 through 19 but it was extended to 63 by many systems. The first three are already opened when the process begins 0: The standard input 1: The standard output 2: The standard error output When the parent process forks a process, the child process inherits the file descriptors of the parent

As an addition to other answers, unix considers everything as a file system. Your keyboard is a file that is read only from the perspective of the kernel. The screen is a write only file. Similarly, folders, input-output devices etc are also considered to be files. Whenever a file is opened, say when the device drivers[for device files] requests an open(), or a process opens an user file the kernel allocates a file descriptor, an integer that specifies the access to that file such it being read only, write only etc. [for reference : https://en.wikipedia.org/wiki/Everything_is_a_file ]