在 bash 中重定向 stdout 与在 c 中使用 fprintf 写入文件(速度)
Redirecting of stdout in bash vs writing to file in c with fprintf (speed)
我想知道哪个选项基本上更快。
我最感兴趣的是重定向机制。我怀疑该文件在程序开始时打开 ./program > file
并在结束时关闭。因此,每次程序输出一些东西时,它应该只是写入一个文件,就像听起来一样简单。是这样吗?那么我想这两个选项在速度方面应该是可比的。
或者由于操作系统需要执行更多的操作,所以可能是更复杂的过程?
是的,你是对的。速度将是相同的。这两种情况的唯一区别在于打开和关闭文件的程序。当您使用 shell 重定向它时,是 shell 打开文件并使句柄作为 stdout
对程序可用。当程序打开文件时,程序会打开文件。之后这两种情况下句柄都是文件句柄,所以速度上应该是绝对没有区别的。
附带说明一下,写入 stdout
的程序可以以更通用的方式使用。例如,您可以说
./program | ssh remotehost bash -c "cat > file"
这将导致程序的输出在 remotehost
上写入 file
。当然,在这种情况下,没有像您在问题中所做的比较。
stdout
是一个 FILE
句柄,fprintf
写入文件句柄,所以两种情况下的速度非常相似。事实上 printf("Some string")
等同于 fprintf(stdout, "Some string")
。我就不多说了:)
这些选项之间没有太大区别(除了将文件作为严格选项会降低程序的灵活性)。
为了比较这两种方法,让我们检查一下,魔法实体背后是什么 FILE*
:
所以在这两种情况下,我们都有一个 FILE*
对象,一个文件描述符 fd - 通往 OS 内核和内核基础设施的网关提供对文件或用户终端的访问,这应该(除非 libc 有一些 special 初始值设定项用于 stdout 或内核专门处理 fd = 1 的文件)。
与 fopen()
相比,bash 重定向如何工作?
当 bash 重定向文件时:
fork() // new process is created
fd = open("file", ...) // open new file
close(1) // get rid of fd=1 pointing to /dev/pts device
dup2(fd, 1) // make fd=1 point to opened file
close(fd) // get rid of redundant fd
execve("a") // now "a" will have file as its stdout
// in a
stdout = fdopen(1, ...)
当您自己打开文件时:
fork() // new process is created
execve("a") // now "a" will have file as its stdout
stdout = fdopen(1, ...)
my_file = fopen("file", ...)
fd = open("file", ...)
my_file = fdopen(fd, ...)
如您所见,主要的bash区别在于文件描述符。
我想知道哪个选项基本上更快。
我最感兴趣的是重定向机制。我怀疑该文件在程序开始时打开 ./program > file
并在结束时关闭。因此,每次程序输出一些东西时,它应该只是写入一个文件,就像听起来一样简单。是这样吗?那么我想这两个选项在速度方面应该是可比的。
或者由于操作系统需要执行更多的操作,所以可能是更复杂的过程?
是的,你是对的。速度将是相同的。这两种情况的唯一区别在于打开和关闭文件的程序。当您使用 shell 重定向它时,是 shell 打开文件并使句柄作为 stdout
对程序可用。当程序打开文件时,程序会打开文件。之后这两种情况下句柄都是文件句柄,所以速度上应该是绝对没有区别的。
附带说明一下,写入 stdout
的程序可以以更通用的方式使用。例如,您可以说
./program | ssh remotehost bash -c "cat > file"
这将导致程序的输出在 remotehost
上写入 file
。当然,在这种情况下,没有像您在问题中所做的比较。
stdout
是一个 FILE
句柄,fprintf
写入文件句柄,所以两种情况下的速度非常相似。事实上 printf("Some string")
等同于 fprintf(stdout, "Some string")
。我就不多说了:)
这些选项之间没有太大区别(除了将文件作为严格选项会降低程序的灵活性)。
为了比较这两种方法,让我们检查一下,魔法实体背后是什么 FILE*
:
所以在这两种情况下,我们都有一个 FILE*
对象,一个文件描述符 fd - 通往 OS 内核和内核基础设施的网关提供对文件或用户终端的访问,这应该(除非 libc 有一些 special 初始值设定项用于 stdout 或内核专门处理 fd = 1 的文件)。
与 fopen()
相比,bash 重定向如何工作?
当 bash 重定向文件时:
fork() // new process is created
fd = open("file", ...) // open new file
close(1) // get rid of fd=1 pointing to /dev/pts device
dup2(fd, 1) // make fd=1 point to opened file
close(fd) // get rid of redundant fd
execve("a") // now "a" will have file as its stdout
// in a
stdout = fdopen(1, ...)
当您自己打开文件时:
fork() // new process is created
execve("a") // now "a" will have file as its stdout
stdout = fdopen(1, ...)
my_file = fopen("file", ...)
fd = open("file", ...)
my_file = fdopen(fd, ...)
如您所见,主要的bash区别在于文件描述符。