“ Bash文件描述符”和“ Linux文件描述符”有什么区别?

时间:2019-04-18 04:11:37

标签: linux bash

我正在调和这两个看似相似的概念。

在Bash中,允许一个人进行任意重定向,并且重要的是,使用一个人选择的文件描述符号。但是,在Linux中,调用过程无法选择getAllRestaurants调用(AFAIK)返回的值。

因此,Bash fd号码是否与系统调用返回的fd号码相同?如果没有,有什么区别?

1 个答案:

答案 0 :(得分:3)

这里有一个小实验,可能会为您提供一些选择,让您在bash中打开文件描述符时发生了什么:

> cat test.txt
foobar!

> cat test.sh
#!/bin/bash
exec 17<test.txt
read -u 17 line
echo "$line"
exec 17>&-

> strace ./test.sh
//// A bunch of stuff omitted so we can skip to the interesting part...
open("test.txt", O_RDONLY)              = 3
fcntl(17, F_GETFD)                      = -1 EBADF (Bad file descriptor)
dup2(3, 17)                             = 17
close(3)                                = 0
fcntl(17, F_GETFD)                      = 0
ioctl(17, TCGETS, 0x7ffc56f093f0)       = -1 ENOTTY (Inappropriate ioctl for device)
lseek(17, 0, SEEK_CUR)                  = 0
read(17, "foobar!\n", 128)              = 8
write(1, "foobar!\n", 8foobar!)         = 8
fcntl(17, F_GETFD)                      = 0
fcntl(17, F_DUPFD, 10)                  = 10
fcntl(17, F_GETFD)                      = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
close(17)                               = 0

回答您问题的部分是它在open()上调用test.txt的位置,返回值3。这是您在C程序中执行的最有可能的结果,因为文件描述符0、1和2(即stdinstdoutstderr)一开始都是打开的。数字3只是下一个可用的文件描述符。

我们在bash脚本的strace输出中也看到了这一点。 bash的不同之处在于,它随后调用fcntl(17, F_GETFD)来检查文件描述符17是否已打开(因为它想将fd用于test.txt)。然后,当fcntl返回EBADF表示没有打开此类fd时,bash知道可以自由使用它。因此,它随后调用dup2(3, 17)来使fd 17成为fd 3的副本。最后,它在fd 3上调用close()再次释放它,从而使fd 17保留(仅 fd 17)作为test.txt的打开文件描述符。

因此,您的问题的答案是bash文件描述符不是与其他所有人使用的“普通”文件描述符不同的特殊生物。他们实际上是同一回事。您可以轻松地在C程序中使用相同的技巧来打开具有所选文件描述符编号的文件。

另外,值得指出的是,bash在调用open()时并没有真正选择自己的文件描述符。像其他所有人一样,它必须与open()返回的收益有关。您的bash脚本中真正发生的全部是烟雾和镜像(通过dup2()),使其看起来好像您可以选择自己的文件描述符。