![使用 fd 3 安全吗?](https://linux22.com/image/97773/%E4%BD%BF%E7%94%A8%20fd%203%20%E5%AE%89%E5%85%A8%E5%90%97%EF%BC%9F.png)
有几个问题使用它来执行多个输出管道之类的事情,而不使用进程替换:
为此仅使用固定的 fd 编号是否安全?是否有可能某个程序已经按照描述使用它这里我们会覆盖一些重要的内容或读取一些不相关的内容吗?
答案1
是否有可能某个程序已经在使用它
不会。您会看到,I/O 重定向发生在程序或脚本启动之前。
通常,当程序或脚本启动时,仅打开标准描述符(0/标准输入、1/标准输出和2/标准错误)。 (它们可能指的是终端、设备、文件,甚至是网络套接字;但它们应该是打开的。我们不是“关闭”一个,而是将不需要的描述符从/到重定向/dev/null
,本质上是“无处”/“无” .)
程序通过系统调用使用描述符,就像open
使用空闲描述符一样。也就是说,它们不要求内核打开文件或套接字到特定的描述符,内核选择描述符。因此,程序使用附加描述符的唯一情况是当程序启动时预计它已经打开。有一些像这样的罕见实用程序守护进程 - 除了标准描述符之外,它们还期望如果描述符 3 在它们启动时打开,则它会连接到它们的管理服务(或类似的东西)。
如果一个程序决定使用硬编码描述符(唯一的原因是它分叉并执行另一个程序期望该描述符要打开;正如我所说,这种情况非常罕见),当程序用它的用途替换它时,已经打开的描述符会被关闭。 (顺便说一句,当程序表明他们想要使用特定的描述符时,内核会执行关闭操作,例如dup2()
在 POSIXy 系统中;进程不需要关心。)
Shell 脚本(Bash 和 sh)使用固定的描述符编号,因此脚本可能使用特定的描述符来执行某些输入/输出重定向。但是,当发生这种情况时,之前的重定向将被忽略,并且不会产生任何效果,因为脚本假定描述符已关闭。 (如果描述符是打开的,并且脚本将该描述符用于某些内部内容,则当脚本重定向它时,原始描述符将首先由内核关闭,并且出于前一段中提到的原因。对于任何类型要发生数据泄漏,脚本必须专门测试如果描述符已经打开,并且避免重定向它。)
另请注意,Fortran I/O 单元或通道与描述符无关,即使两者都使用数字进行标识。因此,即使 Fortran 程序使用单元 10,也不意味着它使用描述符 10。
为此仅使用固定的 fd 编号是否安全?
是的。 POSIX 规定一个程序至少可以打开 20 个描述符,因此 3 到 19 之间的任何固定数量都应该可以正常工作。
关键点是很好地记录它,最好是在脚本开头的简短注释中(对于脚本),或者在用法(-h
或--help
命令行选项)和手册页(对于程序)中。
对于脚本,您可以假设如果发生冲突(如果发生冲突,则将是“脚本根本不起作用,因为程序启动后管道就会关闭”,如上所述),用户可以更改固定描述符数量以更好地满足他们的需求。因此,作为剧本作者,你的任务就是提前计划,并让后续的人更容易计划。 (描述您的意图和整体设计的清晰注释就足够了;没有必要将描述符编号设置为变量,或描述脚本所做的每个小动作。)
对于程序来说,使其运行时可配置是一个好主意。例如,您可以让您的程序/守护进程使用描述符 3(如果打开)用于具有图形用户界面的特殊控制协议;但是,使用某些命令行选项(例如“-c 5”),使用命名描述符(或者,与-c /dev/name
或-c named-pipe
或-c :socketpath
使用指定的文件、命名管道或本地域套接字)。这样用户就可以轻松解决与脚本的任何冲突。