129

这可能在许多常见问题解答中 - 而不是使用:

cat file | command

(这被称为无用的猫),正确的方法应该是:

command < file

在第二种“正确”方式中 - 操作系统不必产生额外的进程。
尽管知道这一点,但我继续使用无用的猫有两个原因。

  1. 更美观——我喜欢数据只从左到右均匀移动。并且更容易cat用其他东西替换(gzcat, echo, ...),添加第二个文件或插入新过滤器(pv, mbuffer, grep...)。

  2. 我“感觉”在某些情况下它可能会更快。更快,因为有 2 个进程,第一个 ( cat) 执行读取,第二个执行任何操作。它们可以并行运行,这意味着有时执行速度更快。

我的逻辑是否正确(出于第二个原因)?

4

9 回答 9

101

直到今天,当一些新秀试图将UUOC钉在我身上以获得我的答案之一时,我才知道该奖项。这是一个cat file.txt | grep foo | cut ... | cut .... 我给了他一些想法,然后才访问了他给我的链接,其中提到了奖项的起源和这样做的做法。进一步的搜索使我想到了这个问题。有点不幸的是,尽管有意识地考虑,但没有一个答案包括我的理由。

我并不想在回应他时采取防御措施。毕竟,在我年轻的时候,我会写这个命令,grep foo file.txt | cut ... | cut ...因为每当你执行频繁grep的 single 时,你都会学习 file 参数的位置,并且很容易知道第一个是模式,后面的是文件名。

当我回答这个问题时,这是一个有意识的选择cat,部分原因是“品味高”(用 Linus Torvalds 的话),但主要是出于令人信服的功能原因。

后一个原因更重要,所以我先说出来。当我提供管道作为解决方案时,我希望它是可重用的。一条管道很可能会添加到另一条管道的末端或拼接到另一条管道中。在这种情况下,为 grep 提供一个文件参数会破坏可重用性,并且如果文件参数存在,很可能会默默地这样做而不会出现错误消息。IE。当您期望同时包含和的行数时,grep foo xyz | grep bar xyz | wc将为您提供xyz包含的行数。在使用管道之前必须将参数更改为管道中的命令很容易出错。再加上无声失败的可能性,它就变成了一种特别阴险的做法。barfoobar

前一个原因也不是不重要的,因为很多“好品味”只是一种直觉的潜意识理由,比如上面那些无声的失败,当某个需要教育的人说“但不是那只猫没用”。

但是,我会尽量让我意识到我提到的前一个“好品味”的原因。这个原因与 Unix 的正交设计精神有关。grep没有cutls也没有grep。因此至少grep foo file1 file2 file3有悖于设计精神。正交的做法是cat file1 file2 file3 | grep foo。现在,grep foo file1只是 的一个特例grep foo file1 file2 file3,如果你不以同样的方式对待它,你至少会用尽脑时钟周期来试图避免无用的猫奖。

这导致我们的论点grep foo file1 file2 file3是连接,并且cat连接所以它是正确的,cat file1 file2 file3但是因为cat没有连接,cat file1 | grep foo所以我们违反了cat全能 Unix 的精神。好吧,如果是这种情况,那么 Unix 将需要一个不同的命令来读取一个文件的输出并将它的输出到标准输出(而不是对它进行分页或任何纯粹的输出到标准输出)。所以你会遇到这样的情况,你说cat file1 file2或者你说dog file1,并认真记住要避免cat file1以避免获得奖励,同时也要避免,dog file1 file2因为如果指定了多个文件,希望设计dog会抛出错误。

希望在这一点上,您对 Unix 设计者表示同情,因为他们没有包含单独的命令来将文件发送到标准输出,同时还cat为连接命名而不是给它其他名称。实际上,<edit>删除了不正确的注释是一种有效的无复制工具,可以将文件吐出到标准输出,您可以将其放置在管道的开头,因此 Unix 设计人员确实为此专门包含了一些内容<<</edit>

下一个问题是,为什么只有将一个文件或多个文件串联到标准输出而不进行任何进一步处理的命令很重要?一个原因是要避免让每个在标准输入上运行的 Unix 命令都知道如何解析至少一个命令行文件参数并将其用作输入(如果存在)。第二个原因是避免用户必须记住:(a)文件名参数的去向;(b) 避免上面提到的静默管道错误。

这让我们明白为什么grep会有额外的逻辑。其基本原理是允许用户流畅地使用经常使用的命令并且独立地使用(而不是作为管道)。这是对正交性的轻微妥协,以显着提高可用性。并非所有命令都应该这样设计,不经常使用的命令应该完全避免文件参数的额外逻辑(记住额外的逻辑会导致不必要的脆弱性(可能出现错误))。例外情况是允许文件参数,例如grep. (顺便说一句,请注意,ls有一个完全不同的理由不仅要接受,而且还需要文件参数)

grep最后,如果在指定文件参数时标准输入也可用,那么如果像(但不一定ls)这样的异常命令会生成错误,本可以做得更好。

于 2013-05-18T00:04:46.610 回答
66

没有!

首先,重定向发生在命令的哪个位置并不重要。因此,如果您喜欢重定向到命令左侧,那很好:

< somefile command

是相同的

command < somefile

其次,当您使用管道时,会发生n + 1 个进程和一个子外壳。它绝对是更慢的。在某些情况下, n会为零(例如,当您重定向到内置的 shell 时),因此使用cat您完全不必要地添加了一个新进程。

概括地说,每当您发现自己在使用管道时,都值得花 30 秒来看看是否可以消除它。(但可能不值得花费超过 30 秒的时间。)以下是一些经常不必要地使用管道和进程的示例:

for word in $(cat somefile); … # for word in $(<somefile); … (or better yet, while read < somefile)

grep something | awk stuff; # awk '/something/ stuff' (similar for sed)

echo something | command; # command <<< something (although echo would be necessary for pure POSIX)

随意编辑以添加更多示例。

于 2012-07-29T15:49:35.447 回答
34

为猫辩护:

是的,

   < input process > output 

或者

   process < input > output 

效率更高,但是很多调用没有性能问题,所以你不在乎。

人体工学原因:

我们习惯于从左到右阅读,所以像这样的命令

    cat infile | process1 | process2 > outfile

很容易理解。

    process1 < infile | process2 > outfile

必须跳过process1,然后从左到右读取。这可以通过以下方式治愈:

    < infile process1 | process2 > outfile

看起来,好像有一个箭头指向左边,那里什么都没有。更令人困惑和看起来像花哨的引用是:

    process1 > outfile < infile

并且生成脚本通常是一个迭代过程,

    cat file 
    cat file | process1
    cat file | process1 | process2 
    cat file | process1 | process2 > outfile

您可以逐步看到自己的进步,而

    < file 

甚至不起作用。简单的方法不太容易出错,并且符合人体工程学的命令连接使用 cat 很简单。

另一个主题是,大多数人在使用计算机之前很久就已经接触过 > 和 < 作为比较运算符,并且在使用计算机作为程序员时,他们更经常接触到这些操作符。

并且用 < 和 > 比较两个操作数是反交换的,这意味着

(a > b) == (b < a)

我记得第一次使用 < 进行输入重定向,我担心

a.sh < file 

可能意味着相同

file > a.sh

并以某种方式覆盖我的 a.sh 脚本。这可能是很多初学者的问题。

罕见的差异

wc -c journal.txt
15666 journal.txt
cat journal.txt | wc -c 
15666

后者可以直接用于计算。

factor $(cat journal.txt | wc -c)

当然 < 也可以在这里使用,而不是文件参数:

< journal.txt wc -c 
15666
wc -c < journal.txt
15666
    

但谁在乎 - 15k?

如果我偶尔遇到问题,我肯定会改变我调用 cat 的习惯。

当使用非常大或很多很多文件时,避免 cat 很好。对于大多数问题,cat 的使用是正交的、离题的,不是问题。

每隔一个shell话题就开始这些无用无用的cat讨论只会令人讨厌和无聊。在处理性能问题时,获得生命并等待成名。

于 2018-03-13T10:46:39.600 回答
30

我不同意大多数过分自鸣得意的 UUOC 奖的例子,因为在教别人时,cat它是任何命令或硬壳复杂命令管道的方便占位符,这些命令产生适合正在讨论的问题或任务的输出。

在 Stack Overflow、ServerFault、Unix 和 Linux 等站点或任何 SE 站点上尤其如此。

如果有人特别询问优化,或者如果您想添加有关它的额外信息,那么很好,谈谈使用 cat 是如何低效的。但是不要因为他们选择在他们的例子中追求简单和易于理解而不是看着我,我是多么酷!复杂。

简而言之,因为猫并不总是猫。

也因为大多数喜欢到处授予 UUOC 的人这样做是因为他们更关心炫耀自己有多“聪明”,而不是帮助或教别人。实际上,他们证明他们可能只是另一个找到一根小棍子来击败同龄人的新手。


更新

这是我在https://unix.stackexchange.com/a/301194/7696的答案中发布的另一个 UUOC :

sqlq() {
  local filter
  filter='cat'

  # very primitive, use getopts for real option handling.
  if [ "$1" == "--delete-blank-lines" ] ; then
    filter='grep -v "^$"'
    shift
  fi

  # each arg is piped into sqlplus as a separate command
  printf "%s\n" "$@" | sqlplus -S sss/eee@sid | $filter
}

UUOC 学究会说这是一个 UUOC,因为很容易将$filter默认设置为空字符串并让if语句执行filter='| grep -v "^$"',但是 IMO,通过不将管道字符嵌入到 中$filter,这种“无用”cat服务于自我记录事实的极其有用的目的that $filteron printfline 不仅仅是 的另一个参数sqlplus,它是一个可选的用户可选择的输出过滤器。

如果需要有多个可选的输出过滤器,则选项处理可以根据需要随时追加| whatever-$filter管道cat中的额外一个不会损害任何东西或导致任何明显的性能损失。

于 2015-09-21T06:57:09.473 回答
27

在 UUoC 版本中,cat必须将文件读入内存,然后将其写入管道,并且命令必须从管道中读取数据,因此内核必须将整个文件复制3次,而在重定向的情况下,内核只需复制文件一次。做一件事比做三遍要快。

使用:

cat "$@" | command

是完全不同且不一定无用的cat. 如果命令是接受零个或多个文件名参数并依次处理它们的标准过滤器,它仍然没有用。考虑这个tr命令:它是一个纯粹的过滤器,忽略或拒绝文件名参数。要将多个文件提供给它,您必须cat如图所示使用。(当然,有一个单独的讨论认为 的设计tr不是很好;没有真正的理由不能将其设计为标准过滤器。)如果您希望命令将所有输入视为单个文件而不是多个单独的文件,即使该命令会接受多个单独的文件:例如,wc就是这样一个命令。

这种cat single-file情况是无条件无用的。

于 2012-07-29T16:27:23.927 回答
18

另一个问题是管道可以默默地掩盖子外壳。对于此示例,我将替换catecho,但存在相同的问题。

echo "foo" | while read line; do
    x=$line
done

echo "$x"

您可能希望x包含foo,但事实并非如此。您设置的x子shell 是为执行while循环而生成的。x在启动管道的 shell 中有一个不相关的值,或者根本没有设置。

在 bash4 中,您可以配置一些 shell 选项,以便管道的最后一个命令与启动管道的命令在同一个 shell 中执行,但是您可以试试这个

echo "foo" | while read line; do
    x=$line
done | awk '...'

并且x再次位于while的子shell 的本地。

于 2012-07-29T15:56:27.157 回答
17

作为经常指出这一点和许多其他 shell 编程反模式的人,我觉得有必要,迟来的,权衡一下。

Shell 脚本在很大程度上是一种复制/粘贴语言。对于大多数编写 shell 脚本的人来说,他们并不是在学习语言;这只是他们必须克服的障碍,才能继续用他们实际上有点熟悉的语言做事。

在这种情况下,我认为传播各种 shell 脚本反模式具有破坏性,甚至可能具有破坏性。理想情况下,某人在 Stack Overflow 上找到的代码应该可以复制/粘贴到他们的环境中,而只需最少的更改和不完全理解。

在网上众多的 shell 脚本资源中,Stack Overflow 的不同寻常之处在于,用户可以通过编辑网站上的问题和答案来帮助塑造网站的质量。但是,代码编辑可能会出现问题,因为很容易进行代码作者不希望的更改。因此,我们倾向于留下评论以建议对代码进行更改。

UUCA 和相关的反模式注释不仅适用于我们注释的代码的作者;它们同样是一个警告购买者,可以帮助网站的读者了解他们在此处找到的代码中的问题。

我们不能希望在 Stack Overflow 上没有答案推荐无用cat的 s(或未引用的变量,或chmod 777,或大量其他反模式瘟疫)的情况,但我们至少可以帮助教育即将复制的用户/将此代码粘贴到执行数百万次的脚本的最内部紧密循环中。

就技术原因而言,传统观点是我们应该尽量减少外部进程的数量;在编写 shell 脚本时,这仍然是一个很好的一般指导。

于 2017-12-11T05:28:47.183 回答
10

我经常cat file | myprogram在例子中使用。有时我被指责无用使用猫(http://porkmail.org/era/unix/award.html)。我不同意,原因如下:

  • 很容易理解发生了什么。

    读取 UNIX 命令时,您需要一个命令后跟参数,然后是重定向。可以将重定向放在任何地方,但很少见 - 因此人们将很难阅读该示例。我相信

    cat foo | program1 -o option -b option | program2
    

    比阅读更容易

    program1 -o option -b option < foo | program2
    

    如果你把重定向移到开头,你会让不习惯这种语法的人感到困惑:

    < foo program1 -o option -b option | program2
    

    并且示例应该易于理解。

  • 很容易改变。

    如果您知道程序可以读取cat,您通常可以假设它可以读取任何输出到 STDOUT 的程序的输出,因此您可以根据自己的需要调整它并获得可预测的结果。

  • 它强调如果 STDIN 不是文件,程序不会失败。

    假设如果program1 < foo有效,那么cat foo | program1也将有效是不安全的。但是,可以安全地假设相反。如果 STDIN 是一个文件,这个程序就可以工作,但是如果输入是一个管道,这个程序就会失败,因为它使用了 seek:

    # works
    < foo perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    
    # fails
    cat foo | perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    

性能成本

做额外的cat. 为了了解我运行了多少测试来模拟基线 ( cat)、低吞吐量 ( bzip2)、中等吞吐量 ( gzip) 和高吞吐量 ( grep)。

cat $ISO | cat
< $ISO cat
cat $ISO | bzip2
< $ISO | bzip2
cat $ISO | gzip
< $ISO gzip
cat $ISO | grep no_such_string
< $ISO grep no_such_string

测试在低端系统 (0.6 GHz) 和普通笔记本电脑 (2.2 GHz) 上运行。它们在每个系统上运行 10 次,并选择最佳时间来模拟每次测试的最佳情况。$ISO 是 ubuntu-11.04-desktop-i386.iso。(这里更漂亮的表格:http: //oletange.blogspot.com/2013/10/useless-use-of-cat.html

CPU                       0.6 GHz ARM
Command                   cat $ISO|                        <$ISO                            Diff                             Diff (pct)
Throughput \ Time (ms)    User       Sys        Real       User       Sys        Real       User       Sys        Real       User       Sys        Real
Baseline (cat)                     55      14453      33090         23       6937      33126         32       7516        -36        239        208         99
Low (bzip2)                   1945148      16094    1973754    1941727       5664    1959982       3420      10430      13772        100        284        100
Medium (gzip)                  413914      13383     431812     407016       5477     416760       6898       7906      15052        101        244        103
High (grep no_such_string)      80656      15133      99049      79180       4336      86885       1476      10797      12164        101        349        114

CPU                       Core i7 2.2 GHz
Command                   cat $ISO|           <$ISO             Diff          Diff (pct)
Throughput \ Time (ms)    User     Sys Real   User   Sys Real   User Sys Real User       Sys Real
Baseline (cat)                    0 356    215      1  84     88    0 272  127          0 423  244
Low (bzip2)                  136184 896 136765 136728 160 137131 -545 736 -366         99 560   99
Medium (gzip)                 26564 788  26791  26332 108  26492  232 680  298        100 729  101
High (grep no_such_string)      264 392    483    216  84    304   48 308  179        122 466  158

结果表明,对于中低吞吐量,成本约为 1%。这完全在测量的不确定性范围内,因此在实践中没有区别。

对于高吞吐量,差异更大,两者之间存在明显差异。

这导致了结论:您应该使用<而不是cat |if:

  • 处理的复杂度类似于简单的grep
  • 性能比可读性更重要。

否则无论你使用<还是都没有关系cat |

因此,只有在以下情况下,您才应该授予 UUoC 奖:

  • 您可以衡量绩效的显着差异(在颁奖时公布您的衡量标准)
  • 性能比可读性更重要。
于 2019-01-05T10:19:11.000 回答
-3

我认为(传统方式)使用管道要快一点;在我的盒子上,我使用strace命令查看发生了什么:

不带管道:

toc@UnixServer:~$ strace wc -l < wrong_output.c
execve("/usr/bin/wc", ["wc", "-l"], [/* 18 vars */]) = 0
brk(0)                                  = 0x8b50000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ad000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=29107, ...}) = 0
mmap2(NULL, 29107, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77a5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1552584, ...}) = 0
mmap2(NULL, 1563160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7627000
mmap2(0xb779f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x178) = 0xb779f000
mmap2(0xb77a2000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb77a2000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7626000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb76268d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb779f000, 8192, PROT_READ)   = 0
mprotect(0x804f000, 4096, PROT_READ)    = 0
mprotect(0xb77ce000, 4096, PROT_READ)   = 0
munmap(0xb77a5000, 29107)               = 0
brk(0)                                  = 0x8b50000
brk(0x8b71000)                          = 0x8b71000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=5540198, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7426000
mmap2(NULL, 1507328, PROT_READ, MAP_PRIVATE, 3, 0x2a8) = 0xb72b6000
close(3)                                = 0
open("/usr/share/locale/locale.alias", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ac000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2570
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb77ac000, 4096)                = 0
open("/usr/share/locale/fr_FR.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr_FR.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr_FR/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=316721, ...}) = 0
mmap2(NULL, 316721, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7268000
close(3)                                = 0
open("/usr/lib/i386-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=26064, ...}) = 0
mmap2(NULL, 26064, PROT_READ, MAP_SHARED, 3, 0) = 0xb7261000
close(3)                                = 0
read(0, "#include<stdio.h>\n\nint main(int "..., 16384) = 180
read(0, "", 16384)                      = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7260000
write(1, "13\n", 313
)                     = 3
close(0)                                = 0
close(1)                                = 0
munmap(0xb7260000, 4096)                = 0
close(2)                                = 0
exit_group(0)                           = ?

并使用管道:

toc@UnixServer:~$ strace cat wrong_output.c | wc -l
execve("/bin/cat", ["cat", "wrong_output.c"], [/* 18 vars */]) = 0
brk(0)                                  = 0xa017000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb774b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=29107, ...}) = 0
mmap2(NULL, 29107, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7743000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1552584, ...}) = 0
mmap2(NULL, 1563160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75c5000
mmap2(0xb773d000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x178) = 0xb773d000
mmap2(0xb7740000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7740000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75c4000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75c48d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb773d000, 8192, PROT_READ)   = 0
mprotect(0x8051000, 4096, PROT_READ)    = 0
mprotect(0xb776c000, 4096, PROT_READ)   = 0
munmap(0xb7743000, 29107)               = 0
brk(0)                                  = 0xa017000
brk(0xa038000)                          = 0xa038000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=5540198, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb73c4000
mmap2(NULL, 1507328, PROT_READ, MAP_PRIVATE, 3, 0x2a8) = 0xb7254000
close(3)                                = 0
fstat64(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
open("wrong_output.c", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=180, ...}) = 0
read(3, "#include<stdio.h>\n\nint main(int "..., 32768) = 180
write(1, "#include<stdio.h>\n\nint main(int "..., 180) = 180
read(3, "", 32768)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
13

您可以使用更多和更长的命令进行一些测试,stracetime获得良好的基准测试。

于 2012-07-29T18:38:15.257 回答