与维基百科相比,什么样的文件描述符描述更简单?为什么需要它们?比如说,以壳进程为例,它是如何应用的呢? 进程表是否包含多个文件描述符?如果是,为什么?
当前回答
除了以上所有简化的回答。
如果使用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
其他回答
除了以上所有简化的回答。
如果使用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
其他答案补充了很好的内容。我只是说说我的看法。
根据维基百科,我们可以肯定地知道:文件描述符是非负整数。我认为最重要的一点是:
文件描述符绑定到进程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)和 符号链接
任何操作系统都有正在运行的进程(p),比如p1、p2、p3等等。每个进程通常会持续使用文件。
每个过程都由一个过程树(或者另一种说法是进程表)组成。
通常,操作系统用数字表示每个进程中的每个文件(也就是说,在每个进程树/表中)。
进程中使用的第一个文件是file0,第二个是file1,第三个是file2,依此类推。
任何这样的数字都是文件描述符。
文件描述符通常是整数(0、1、2而不是0.5、1.5、2.5)。
假设我们经常将过程描述为“进程表”,并且假设表格有行(条目),我们可以说每个条目中的文件描述符单元格用于表示整个条目。
以类似的方式,当您打开一个网络套接字时,它有一个套接字描述符。
在某些操作系统中,您可能会耗尽文件描述符,但这种情况极为罕见,普通计算机用户不必为此担心。
文件描述符可能是全局的(进程A开始于0,结束于1;进程B开始于2,结束于3)等等,但据我所知,通常在现代操作系统中,文件描述符不是全局的,实际上是特定于进程的(进程A开始于0,结束于5,而进程B开始于0,结束于10)。
关于文件描述符的更多要点:
文件描述符(FD)是非负整数(0,1,2,…),它们与所打开的文件相关联。 0、1、2是标准FD,对应于程序启动时默认为shell打开的STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO(在unistd.h中定义)。 FD是按顺序分配的,这意味着尽可能低的未分配整数值。 特定进程的FD可以在/proc/$pid/ FD(在基于Unix的系统上)中看到。
这里提供的所有答案都很棒,这是我的版本
文件描述符是非负整数,充当“文件”或I/O资源(如管道、套接字或数据流)的抽象句柄。这些描述符帮助我们与这些I/O资源进行交互,并使使用它们变得非常容易。I/O系统对于用户进程来说是一个字节流(I/O流)。Unix进程使用描述符(小的无符号整数)来引用I/O流。与I/O操作相关的系统调用以一个描述符作为参数。
有效的文件描述符范围从0到可配置的最大描述符数(ulimit, /proc/sys/fs/file-max)。内核为FD表的std输入(0),std输出(1)和std错误(2)分配desc.。如果文件打开失败,fd返回-1。
当进程成功请求打开一个文件时,内核返回一个文件描述符,该描述符指向内核全局文件表中的一个条目。文件表项包含文件的inode、字节偏移量和该数据流的访问限制(只读、只写等)等信息。