首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bash文件描述符与Linux文件描述符

Bash文件描述符与Linux文件描述符
EN

Stack Overflow用户
提问于 2019-04-18 04:11:36
回答 1查看 248关注 0票数 0

我只是试图调和这两个看似相似的概念。

在Bash中,允许任意重定向,重要的是使用所选的文件描述符号。但是,在Linux中,调用进程不能选择open调用(AFAIK)返回的值。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-18 04:35:52

下面是一个小小的实验,可以说明在bash中打开文件描述符时发生了什么,并选择了许多内容:

代码语言:javascript
复制
> 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() on test.txt,它返回的值为3。如果您这样做,您很可能在C程序中得到这个值,因为文件描述符0、1和2(即stdinstdoutstderr)都是最初打开的。数字3只是下一个可用的文件描述符。

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

因此,对您的问题的回答是,bash文件描述符并不是与其他人使用的“正常”文件描述符不同的特殊生物。事实上,他们也是一样的。您可以很容易地在C程序中使用相同的技巧来打开您选择的文件描述符号的文件。

此外,值得指出的是,bash在调用open()时并没有真正选择自己的文件描述符。它必须与其他人一样,用open()返回的任何内容来解决问题。在bash脚本中,真正要做的就是(通过dup2())进行一些冒烟和镜像,以使您看起来像是选择了自己的文件描述符。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55739026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档