Ale*_*lex 2 c file-descriptors
如果我希望将所有标准输出重定向到一个文件,我会运行
my_prog 1> out
Run Code Online (Sandbox Code Playgroud)
如果我想对 stderr 做同样的事情,我会运行
my_prog 2> err
Run Code Online (Sandbox Code Playgroud)
但是,我知道在 shell 中还有其他文件描述符。例如,这个问题的最高答案使用第三个文件描述符,可以通过以下方式从命令行发送数据
echo "Some console message" 1>&3
Run Code Online (Sandbox Code Playgroud)
C 程序有没有办法写入这个文件描述符?在没有其他程序读取它时写入它,是否也将其输出发送到终端?
再澄清几件事。在:
echo foo >&3
Run Code Online (Sandbox Code Playgroud)
echo
不写入"foo\n"
其文件描述符 3.echo
始终写入 stdout,写入其文件描述符 1。它write()
使用1
整数作为第一个参数调用系统调用,一个指向内存中的区域的指针foo\n
作为第二个参数和4
( ) 的长度foo\n
作为第三个。
在 C 中,你会写它write(1, "foo\n", 4)
。在上面的代码中,shell在调用之前将 fd 1 重定向到与在 fd 3 上打开相同的打开文件描述echo
(通过dup2()
系统调用)。因此,即使它在功能上是等效的,但它与执行write(3, "foo\n", 4)
. 实际上,它类似于(简化):
if (pid = fork())
waitpid(pid, ...);
else {
dup2(3, 1);
execlp("echo", "foo", 0);
}
Run Code Online (Sandbox Code Playgroud)
并echo
做了一个write(1, "foo\n", 4)
除了在几乎所有 shell 中,echo
都是内置的,所以没有fork
or exec
。相反,外壳会:
saved_stdout = dup(1);
dup2(3, 1);
builtin_echo("foo");
dup2(saved_stdout, 1); close(saved_stdout); /* restore stdout */
Run Code Online (Sandbox Code Playgroud)
(其中builtin_echo()
是write(1, "foo\n", 4)
在同一进程中执行的函数)。
对于执行 的命令write(3, "foo\n", 4)
,您可以查看ksh
/zsh
的print -u3 foo
内置命令。
现在,每个进程都可以随意使用文件描述符。除了 0、1 和 2 按照惯例保留给 stdin、stdout 和 stderr。其他 fds 通常并不特殊,但在 shell(这只是一种类型的应用程序)中,fds 0 到<some-value>
某些值至少为 9 的地方保留供(shell 的)用户使用。外壳不会与它们混合以形成内部汤。例如我saved_stdout = dup(1)
上面是一个近似值。实际上,shell 将确保saved_stdout
将是一个大于 的值<some-value>
。
现在,由于没有附加到 0、1、2 之外的 fd 的约定,您不能指望在 fd 3 上打开任何东西。很可能它会被关闭。或者,如果不是,则脚本的调用者可能只是忘记关闭它(或向其添加O_CLOEXC
标志),因为没有理由让它为您打开,因为没有人希望在 fd 3 上打开任何东西.
如果您知道它已经打开了某些东西,您将使用 fd 3,通常由您事先在同一个脚本中打开,例如:
{
var=$(cmd 2>&1 >&3)
} 3>&1
Run Code Online (Sandbox Code Playgroud)
在我们将 fd 3 定义为dup()
fd 1 的 a之前,将其用于cmd
将dup()
其返回到 fd 1 上。
归档时间: |
|
查看次数: |
9432 次 |
最近记录: |