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


当前回答

我不知道内核代码,但我将在这里补充我的意见,因为我已经思考了一段时间,我认为这将是有用的。

当您打开一个文件时,内核返回一个文件描述符来与该文件进行交互。

文件描述符是您正在打开的文件的API的实现。内核创建这个文件描述符,将其存储在一个数组中,并将其提供给您。

例如,该API需要一个允许您读取和写入文件的实现。

现在,再想想我说过的话,记住所有东西都是文件——打印机、监视器、HTTP连接等等。

这是我阅读https://www.bottomupcs.com/file_descriptors.xhtml后的总结。

其他回答

In simple words, when you open a file, the operating system creates an entry to represent that file and store the information about that opened file. So if there are 100 files opened in your OS then there will be 100 entries in OS (somewhere in kernel). These entries are represented by integers like (...100, 101, 102....). This entry number is the file descriptor. So it is just an integer number that uniquely represents an opened file for the process. If your process opens 10 files then your Process table will have 10 entries for file descriptors.

类似地,当您打开一个网络套接字时,它也由一个整数表示,称为套接字描述符。 我希望你能理解。

A file descriptor is an opaque handle that is used in the interface between user and kernel space to identify file/socket resources. Therefore, when you use open() or socket() (system calls to interface to the kernel), you are given a file descriptor, which is an integer (it is actually an index into the processes u structure - but that is not important). Therefore, if you want to interface directly with the kernel, using system calls to read(), write(), close() etc. the handle you use is a file descriptor.

系统调用上覆盖了一个抽象层,即stdio接口。这比基本的系统调用提供了更多的功能/特性。对于这个接口,您获得的不透明句柄是一个FILE*,它由fopen()调用返回。有很多很多函数使用stdio接口fprintf(), fscanf(), fclose(),它们让你的生活更简单。在C语言中,stdin、stdout和stderr分别是FILE*,在UNIX中分别映射到文件描述符0、1和2。

文件描述符只是任何开放资源的引用。只要您打开一个资源,内核就假定您将对其进行一些操作。所有通过程序和资源的通信都发生在一个接口上,这个接口由文件描述符提供。

由于一个进程可以打开多个资源,所以一个资源可能有多个文件描述符。 你可以通过简单地运行, Ls -li /proc/<pid>/fd/这里的pid是进程的进程id

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

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

文件描述符绑定到进程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)和 符号链接

除了以上所有简化的回答。

如果使用bash脚本处理文件,最好使用文件描述符。

例如: 如果你想读写文件"test.txt",使用文件描述符如下所示:

FILE=$1 # give the name of file in the command line
exec 5<>$FILE # '5' here act as the file descriptor

# Reading from the file line by line using file descriptor
while read LINE; do
    echo "$LINE"
done <&5

# Writing to the file using descriptor
echo "Adding the date: `date`" >&5 
exec 5<&- # Closing a file descriptor