与Wikipedia相比,对文件描述符的更简单描述是什么?为什么需要它们?说,以shell进程为例,它如何应用?
进程表是否包含多个文件描述符。如果是,为什么?
与Wikipedia相比,对文件描述符的更简单描述是什么?为什么需要它们?说,以shell进程为例,它如何应用?
进程表是否包含多个文件描述符。如果是,为什么?
Answers:
简而言之,当您打开文件时,操作系统会创建一个代表该文件的条目,并存储有关该打开文件的信息。因此,如果操作系统中打开了100个文件,则操作系统中(内核中的某个位置)将有100个条目。这些条目由整数表示,例如(... 100,101,102 ....)。该条目号是文件描述符。因此,它只是一个整数,唯一表示操作系统中打开的文件。如果您的进程打开10个文件,那么您的进程表将有10个文件描述符条目。
同样,当您打开网络套接字时,它也由整数表示,称为套接字描述符。我希望你明白。
/proc
始终打开描述符来填充内容。
open()
将为您提供文件描述符3,即使另一个正在运行的进程碰巧有一个文件描述符3。也请参见POSIX的定义open()
:文件描述符当前未针对该进程打开。” (强调)。
文件描述符是一个不透明的句柄,在用户和内核空间之间的接口中使用它来标识文件/套接字资源。因此,当您使用open()
或socket()
(系统调用以连接到内核的接口)时,系统会为您提供文件描述符,该文件描述符是整数(实际上是进程u结构的索引-但这并不重要)。因此,如果您想直接与内核接口,使用系统调用read()
,write()
,close()
等你用手柄的文件描述符。
系统调用上覆盖了一层抽象,即stdio
接口。这提供了比基本系统调用更多的功能。对于此接口,您获得的不透明句柄是FILE*
,由fopen()
调用返回。有迹象表明,用很多很多的功能stdio
接口fprintf()
,fscanf()
,fclose()
,这是那里让您的生活更轻松。在C中,stdin
,stdout
,和stderr
是FILE*
,这在UNIX分别映射到文件描述符0
,1
和2
。
从马口中听到:APUE(Richard Stevens)。
对于内核,所有打开的文件均由文件描述符引用。文件描述符是一个非负数。
当我们打开现有文件或创建新文件时,内核将文件描述符返回到进程。 内核维护着所有正在使用的打开文件描述符的表。文件描述符的分配通常是顺序的,它们将作为空闲文件描述符池中的下一个空闲文件描述符分配给文件。当我们关闭文件时,文件描述符将被释放并可用于进一步分配。
有关更多详细信息,请参见此图像:
当我们想要读取或写入文件时,我们使用open()或create()函数调用返回的文件描述符来标识文件,并将其用作read()或write()的参数。
按照惯例,UNIX System Shell将文件描述符0与进程的Standard Input关联,将文件描述符1与Standard Output关联,并将文件描述符2与 Standard Error。
文件描述符的范围是0到OPEN_MAX。可以使用获取文件描述符最大值ulimit -n
。有关更多信息,请阅读《 APUE手册》的第3章。
osqueryi <<< echo '.all process_open_files'
在bash shell中执行。
其他答案增加了很多东西。我只加我的2美分。
根据Wikipedia,我们可以确定:文件描述符是非负整数。我认为最重要的遗漏是:
文件描述符绑定到进程ID。
我们知道最著名的文件描述符是0、1和2。0对应于STDIN
,1 对应于,2对应STDOUT
于STDERR
。
说,以Shell进程为例,它如何应用?
查看此代码
#>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
第四列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指定文件的类型。TYPE的一些值是:
REG – Regular File
DIR – Directory
FIFO – First In First Out
但是所有文件描述符都是CHR –字符特殊文件(或字符设备文件)
现在,我们可以找出文件描述符STDIN
,STDOUT
并STDERR
易与lsof -p PID
,或,我们可以看到,如果我们相同ls /proc/PID/fd
。
还要注意内核跟踪的文件描述符表与文件表或索引节点表不同。正如其他答案所解释的,这些是分开的。
您可能会问自己,这些文件描述符在物理上在哪里以及/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----
。
只是想回想大多数像OS这样的Linux,它定义了七种文件类型:
有关以下几点的更多要点File Descriptor
:
File Descriptors
(FD)是(0, 1, 2, ...)
与打开的文件关联的非负整数。
0, 1, 2
是与相对应的标准FDSTDIN_FILENO
,STDOUT_FILENO
并且STDERR_FILENO
(在中定义unistd.h
)在程序启动时默认代表Shell打开。
FD按顺序分配,这意味着可能的最低未分配整数值。
可以在/proc/$pid/fd
(基于Unix的系统上)看到针对特定进程的FD 。
作为其他答案的补充,unix将所有内容都视为文件系统。您的键盘是一个从内核角度只读的文件。屏幕是只写文件。类似地,文件夹,输入输出设备等也被视为文件。每当打开文件时,例如,当设备驱动程序(用于设备文件)请求open()或进程打开用户文件时,内核就会分配文件描述符,该整数指定了对该文件的访问权限,因此该文件为只读,仅写等。[供参考:https : //en.wikipedia.org/wiki/Everything_is_a_file ]
文件描述符(FD):
$ ls mydir 2> errorsfile.txt
标准错误的文件描述符为2。
如果没有名为mydir的目录,则命令的输出将保存到文件errorfile.txt中。
使用“ 2>”将错误输出重定向到名为“ errorfile”的文件。 txt”,
因此程序输出不会出现错误。
我希望你能得到答案。
任何操作系统都有正在运行的进程(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结束)。
除了所有简化的响应之外。
如果要使用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