这可能出现在许多常见问题解答中 - 而不是使用:
cat file | command
(这被称为无用的猫),正确的方式应该是:
command < file
在第二种,“正确”的方式 - 操作系统不必产生额外的过程 尽管知道这一点,我继续使用无用的猫有两个原因。
更美观 - 我喜欢数据仅从左向右均匀移动。并且更容易将cat
替换为其他内容(gzcat
,echo
,...),添加第二个文件或插入新过滤器(pv
,{{1} },mbuffer
...)。
我“觉得”在某些情况下可能会更快。更快,因为有2个进程,1st(grep
)执行读取,第二个执行任何操作。它们可以并行运行,这意味着有时可以更快地执行。
我的逻辑是否正确(第二个原因)?
答案 0 :(得分:66)
直到今天,我还没有意识到这个奖项,当时有些新手试图将UUOC放在我身上,以获得我的一个答案。这是cat file.txt | grep foo | cut ... | cut ...
。我给了他一个想法,只有在这样做之后,我才能看到他给我的链接,指的是奖项的起源和这样做的实践。进一步的搜索引导我这个问题。有点不幸的是,尽管有意识地考虑,但没有一个答案包括我的理由。
我并不打算在回应他时采取防御措施。毕竟,在我年轻的时候,我会把命令编写为grep foo file.txt | cut ... | cut ...
,因为无论何时你经常单grep
s,你都会学习文件参数的位置,并且知道第一个是模式和后面的模式是文件名。
当我回答这个问题时,使用cat
是一种有意识的选择,部分原因是因为&#34;品味良好&#34; (用Linus Torvalds的话说)但主要是出于功能上令人信服的原因。
后一个原因更重要,所以我先说出来。当我提供管道作为解决方案时,我希望它可以重复使用。管道很可能会在最后添加或拼接到另一个管道中。在这种情况下,如果文件参数存在,那么grep的文件参数会破坏可重用性,并且很可能静默而没有错误消息。 I. e。当您期望包含grep foo xyz | grep bar xyz | wc
和xyz
的行数时,bar
会在foo
包含bar
的行中显示多少行。在使用之前必须在管道中更改参数的参数很容易出错。再加上沉默失败的可能性,它就变成了一种特别阴险的做法。
之前的原因并非不重要,因为很多&#34; good taste&#34; 对于诸如上面的沉默失败之类的东西来说,仅仅是一个直观的潜意识理论,当你需要接受教育的人说出来时,你无法想到这一点,但这并不是说那只猫没用#34;
然而,我会尽量让自己意识到前者的良好品味&#34;我提到的原因。这个原因与Unix的正交设计精神有关。 grep
cut
和ls
没有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就需要一个不同的命令来读取一个文件的输出并将其吐出到stdout(不是将它分页或者只是纯粹的spit到stdout)。所以你会遇到cat file1 file2
或者你说dog file1
并且认真记得避免cat file1
避免获得奖励的情况,同时也避免dog file1 file2
因为希望设计如果指定了多个文件,则dog
会抛出错误。
希望,在这一点上,你同情Unix设计师没有包含一个单独的命令来将文件吐出到stdout,同时也命名cat
用于连接而不是给它一些其他名称。 <edit>
删除了<
上的错误评论,事实上,<
是一个有效的无副本设施,可以将文件吐出到stdout,您可以在开头定位一个管道,所以Unix设计师确实包含了一些特别针对 </edit>
接下来的问题是,为什么在没有任何进一步处理的情况下将命令仅仅吐出文件或将多个文件连接到stdout很重要?一个原因是避免让每个运行在标准输入上的Unix命令知道如何解析至少一个命令行文件参数,并将其用作输入(如果存在)。第二个原因是避免用户必须记住:(a)文件名参数的去向; (b)避免如上所述的无声管道错误。
这让我们知道为什么grep
确实有额外的逻辑。其基本原理是允许用户流畅地使用经常使用的命令,并且基于独立(而不是作为管道)。对于可用性的显着增加,这是对正交性的轻微折衷。并非所有命令都应该以这种方式设计,并且不经常使用的命令应该完全避免文件参数的额外逻辑(记住额外的逻辑会导致不必要的脆弱性(bug的可能性))。例外情况是允许文件参数,例如grep
。 (顺便说一句,请注意ls
有一个完全不同的理由,不仅要接受,而且几乎需要文件参数)
最后,如果指定文件参数时,如果标准输入也可用,那么如果grep
(但不一定是ls
)这样的异常命令会产生错误,那么可以做得更好的是。 p>
答案 1 :(得分:53)
都能跟得上!
首先,重定向发生在命令的哪个位置并不重要。所以如果你喜欢你的命令左边的重定向,那很好:
< somefile command
与
相同command < somefile
其次,使用管道时会发生 n + 1 进程和子shell。它最明显更慢。在某些情况下, n 将为零(例如,当您重定向到内置shell时),因此通过使用cat
,您将完全不必要地添加新进程。 / p>
作为概括,每当你发现自己使用管道时,值得花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)
随意编辑以添加更多示例。
答案 2 :(得分:27)
使用UUoC版本,cat
必须将文件读入内存,然后将其写入管道,并且命令必须从管道读取数据,因此内核必须复制整个文件三次次,而在重定向的情况下,内核只需复制一次文件。做一次比做三次更快。
使用:
cat "$@" | command
与cat
完全不同,不一定无用。如果命令是接受零个或多个文件名参数的标准过滤器并依次处理它们,那么它仍然是无用的。考虑tr
命令:它是一个忽略或拒绝文件名参数的纯过滤器。要向其提供多个文件,您必须使用cat
,如图所示。 (当然,有一个单独的讨论,tr
的设计不是很好;没有真正的理由它不能被设计为标准过滤器。)如果你想要命令对待这也可能是有效的所有输入都作为单个文件而不是多个单独的文件,即使命令会接受多个单独的文件:例如,wc
就是这样的命令。
cat single-file
案件无条件无用。
答案 3 :(得分:25)
我不同意大多数过度沾沾自喜的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
提供了非常有用的目的,即自我记录$filter
行上printf
不仅仅是sqlplus
行的另一个参数的事实{1}},它是一个可选的用户可选输出过滤器。
如果需要有多个可选输出过滤器,则选项处理可以根据需要随时将| whatever
附加到$filter
- 管道中的一个额外cat
不会出现伤害任何事情或造成任何明显的业绩损失。
答案 4 :(得分:16)
另一个问题是管道可以静默掩盖子壳。对于此示例,我将cat
替换为echo
,但存在同样的问题。
echo "foo" | while read line; do
x=$line
done
echo "$x"
您可能希望x
包含foo
,但事实并非如此。您设置的x
位于子shell中,用于执行while
循环。启动管道的shell中的x
具有不相关的值,或者根本没有设置。
在bash4中,您可以配置一些shell选项,以便管道的最后一个命令在与启动管道的shell相同的shell中执行,但是您可以尝试这个
echo "foo" | while read line; do
x=$line
done | awk '...'
和x
再次位于while
子shell的本地。
答案 5 :(得分:16)
cat的防御:
是的,
< 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来说很简单。
另一个话题是,大多数人都接触过&gt;和&lt;作为比较运算符,早在使用计算机和使用计算机作为程序员之前,就更多地接触到这些。
将两个操作数与&lt;和&gt;是可交换的,这意味着
(a > b) == (b < a)
我记得第一次使用&lt;对于输入重定向,我担心
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)
当然&lt;也可以在这里使用,而不是文件参数:
< journal.txt wc -c
15666
wc -c < journal.txt
15666
但是谁在乎 - 15k?
如果我偶尔会遇到问题,我肯定会改变调用猫的习惯。
当使用非常大或许多文件时,避免使用猫是可以的。对于大多数问题,猫的使用是正交的,偏离主题,而不是问题。
在每个第二个shell主题上开始这些无用的无用的cat讨论只会令人烦恼和无聊。在处理表演问题时,获得生命并等待你的名声。
答案 6 :(得分:11)
作为一个经常指出这个以及其他一些shell编程反模式的人,我觉得有必要,姗姗来迟,权衡。
Shell脚本是一种复制/粘贴语言。对于大多数编写shell脚本的人来说,他们不是在学习语言;这只是他们必须克服的一个障碍,以便继续用他们实际上熟悉的语言来做事。
在这种情况下,我认为传播各种shell脚本反模式具有破坏性,甚至可能具有破坏性。理想情况下,有人在Stack Overflow上找到的代码可以复制/粘贴到他们的环境中,只需要很少的更改和不完整的理解。
在网络上的众多shell脚本资源中,Stack Overflow很不寻常,因为用户可以通过编辑网站上的问题和答案来帮助塑造网站的质量。但是,code edits can be problematic因为很容易进行代码作者不想要的更改。因此,我们倾向于留下评论来建议对代码的更改。
UUCA和相关的反模式评论不仅适用于我们评论的代码的作者;他们同样是一个警告经纪人,以帮助网站的读者了解他们在此处找到的代码中的问题。
我们无法希望达到Stack Overflow上没有答案推荐无用的cat
s(或未引用的变量,或chmod 777
或其他各种反模式瘟疫)的情况,但我们至少可以帮助教育将要复制/粘贴此代码的用户进入他们执行数百万次的脚本中最紧密的循环。
就技术原因而言,传统观点认为我们应尽量减少外部流程的数量;在编写shell脚本时,这仍然是一个很好的一般指导。
答案 7 :(得分:6)
我经常在示例中使用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的程序的输出,因此可以根据自己的需要进行调整并获得可预测的结果。 / p>
如果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
)和高吞吐量({{1 }}。
grep
测试在低端系统(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)
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
结果表明,对于中低吞吐量,成本约为1%。这完全在测量的不确定性之内,因此在实践中没有区别。
对于高吞吐量,差异更大,并且两者之间存在明显差异。
得出结论:如果满足以下条件,则应使用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
而不是<
否则,使用cat |
还是<
都没关系。
因此,仅在以下情况下才应授予UUoC奖励:
答案 8 :(得分:-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
您可以使用strace
和time
命令进行一些测试,使用越来越多的命令进行良好的基准测试。