我正在调和这两个看似相似的概念。
在Bash中,允许一个人进行任意重定向,并且重要的是,使用一个人选择的文件描述符号。但是,在Linux中,调用过程无法选择getAllRestaurants
调用(AFAIK)返回的值。
因此,Bash fd号码是否与系统调用返回的fd号码相同?如果没有,有什么区别?
答案 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(即stdin
,stdout
和stderr
)一开始都是打开的。数字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()
),使其看起来好像您可以选择自己的文件描述符。