把 Linux 想象成一家五星级酒店:你的程序是住客,内核是坐在总台的大堂经理。住客想办任何事——开门取文件、发网络请求、申请内存——都不能自己动手,必须拿起房间里的电话打给总台。这通电话,就是「系统调用」。可麻烦的是,当程序表现异常时——反复找不到文件、被拒绝访问、突然卡死——你根本不知道它到底在总台说了什么。strace 就是酒店装在电话线上的「录音设备」:它一字不漏地记下程序每次拨出的电话——调用了哪个系统调用、传了什么参数、总台回了什么结果。而 ltrace 则是更靠近住客的「随身记录仪」,记的是住客叫服务员跑腿的日常请求(库函数)。有了这两样工具,程序的一切“对外请求”都变成了可回放的通话记录,排查问题就像翻录音带一样简单——这正是后端工程师梦寐以求的“上帝视角”。
对 AI 从业者的价值:模型服务、数据处理脚本在生产环境崩溃时,strace 能把“程序到底卡在哪、缺什么、谁拒绝了它”一锤定音,是后端与运维岗位最实用的五分钟排障利器。
可视化演示
展示strace拦截程序系统调用的过程,跟踪模式实时显示调用流,统计模式展示各调用次数和耗时分布。
本节配有交互动效(进入视口后自动加载,约 3KB)。
跟踪模式 strace拦截程序发出的每个系统调用 实时显示调用名、参数和返回值 strace -p PID
追踪工具概览
酒店的「电话系统」分两层:一层是住客直接打给总台的直线,记录的是必须请内核出面的大事——打开文件、收发网络包、申请内存,这叫「系统调用」;另一层是住客唤服务员来跑腿的日常吩咐,比如 printf 打印一行、malloc 申请一块内存,这叫「库函数」。strace 和 ltrace 这对工具,正好分别在这两层装上「录音设备」。前者盯大事,后者盯小事,分工明确。
在 Linux 的世界里,普通程序运行在「用户态」,凡是要碰文件、开网络、申请内存这些“需要特权”的操作,都必须通过系统调用请求内核代办。为了方便开发者,glibc 标准库把大量系统调用包装成了友好的库函数——你写代码时随手调用的 fopen、printf,其实只是“服务员”,它们内部最终会帮你拨通总台的电话,触发 open、write 这样的系统调用。
strace 利用 Linux 的 ptrace 机制附着到目标进程上:内核每收到一次系统调用,strace 就能截获它的名字、参数和返回值,像录音机一样逐条记录。ltrace 则更进一步,它跟踪的是动态库函数调用——比如 malloc、strlen、puts——这些调用发生在用户态,比系统调用更接近程序自身的逻辑。安装也很简单:Debian/Ubuntu 用 apt install strace ltrace,CentOS 用 yum install strace ltrace。
两套设备装好后,最直观的收获是:当程序报“文件不存在”时,你不再需要猜它找的是哪个路径、以什么方式打开——回放一下 open 那条通话记录,真相立刻摆在眼前。
- 程序起点请求从应用程序发出,此时程序还停留在用户态,不知道内核的细节。
- 库函数封装程序先调用 glibc 提供的函数,如 fopen、printf,这些函数在用户态完成参数整理和格式转换。
- 系统调用落地glibc 把任务包装成内核认识的请求,如 open、write,触发陷入内核态,由内核真正执行。
基础使用入门
录音设备买回来,第一步是学会开机。最简单的用法就是把要监控的命令直接跟在 strace 后面,比如 strace ls -l,回车之后,ls 执行期间拨出的每一通“电话”都会一行行刷在屏幕上。这个动作就像把录音机接到总台线路上,等着住客打电话。
命令的基本格式是 strace [选项] 命令 [参数]。不带任何选项时,跟踪结果默认输出到标准错误流 stderr,而不是标准输出 stdout——这是为了避免监听日志混进程序的正常输出。如果担心刷屏淹没现场,可以加 -o log.txt 把全部记录写进文件,结束后再慢慢回放。
实际使用中有两种追踪场景:追踪一个新启动的程序,直接在 strace 后面跟命令名;附加到一个正在运行的进程,则要用 -p PID,比如 strace -p 1234。多进程程序要加 -f,让 strace 跟着 fork 出来的子进程一起跟踪;想停止录音就按 Ctrl+C,此时 strace 会打印统计信息并退出。
就像录音机要选对磁带一样,-o 指定输出文件能避免海量输出刷屏,-f 则确保不放过“住客让服务员代拨”的子进程通话。学会这四项基础操作,你就已经能独立录制“通话磁带”了。
- strace 命令启动监听工具本身,它是整个排障动作的入口。
- 方括号选项可选的开关集合,如
-o指定输出文件、-f跟踪子进程、-p附加已有进程。 - 目标命令要被录制通话的程序名,strace 会启动它并全程监控。
- 程序参数传给目标程序的命令行参数,会原样转发给被跟踪的程序。
输出信息解读
录音带倒出来,上面是一行行格式工整的通话记录。看懂格式,破案就成功了一半。每一条记录长这样:open("/etc/passwd", O_RDONLY) = 3。左边是系统调用名和参数,等号右边是返回值——整个格式就像电话账单上的“拨打号码、通话时长、结果状态”。
返回值是破案的关键线索。如果返回值是非负整数,比如 3,表示调用成功,程序拿到了文件描述符 3,后续的 read、write 都靠这个编号认路。如果返回 -1,说明调用失败,同时内核会设置一个叫 errno 的错误码。strace 很贴心,会直接把错误名挂在返回值后面,例如 = -1 ENOENT (No such file or directory)。
常见 errno 需要牢记:ENOENT 表示文件或目录不存在;EACCES 表示权限不足;ECONNREFUSED 表示网络连接被拒绝;ETIMEDOUT 表示连接超时。这些错误码就像酒店总台给你的“拒绝理由编号”,每个编号对应一种明确的拒绝对策。
就像听到电话里“您拨打的号码是空号”一样,ENOENT 告诉你路径拼错了或文件压根不在;EACCES 则说明门锁着、你没有钥匙。把 errno 这本“拒绝理由密码本”装进脑子,绝大多数现场都能当场定性。
- 调用名与参数等号左边记录的是系统调用名和括号内的参数,参数决定了这次请求的内容。
- 成功返回值返回非负整数,对文件类调用来说就是文件描述符,是后续操作的凭证。
- 失败与 errno返回 -1 表示失败,真正的失败原因记录在 errno 变量中,如 ENOENT。
过滤器应用
录音设备若不筛选,一天能录上千条通话。真正的高手会先设置“关键词过滤”,只听想听的。strace 的 -e 参数就是这个筛选开关,它决定了哪些通话进录音带、哪些直接丢弃。
最常用的是 -e trace=调用名 白名单,例如 strace -e trace=open,read ./app 只显示 open 和 read 两条调用,其他一律静音。如果想按类别过滤,strace 还预置了几组“主题套餐”:trace=file 看所有文件类调用,trace=network 看网络类,trace=process 看进程管理类,trace=signal 看信号处理类。反过来,用感叹号取反:trace=!write 表示忽略所有 write 调用。
其他常用参数组合:-f 递归跟踪子进程,让录音覆盖整个“家族”;-o 把输出写进文件,避免终端刷屏;-s 控制字符串参数显示的截断长度,默认 32 字节;-p PID 附加到指定进程。多个条件可以用逗号组合,灵活得像给录音机装了智能语音识别。
好比大堂经理只想听“投诉电话”这类关键词,过滤后录音带里只留下有用的片段。尤其是排查线上问题时,全量跟踪会产生几十 MB 日志,而一条精准的 -e trace=network 就能把视野锁定在网络层,效率翻倍。
- -e 选项进入“筛选设置”模式的开关,后面跟的表达式决定监听范围。
- trace 字段按系统调用名过滤,等号右边是要保留的调用名单。
- 逗号名单多个调用名用逗号分隔,表示这些调用全部进入录音范围。
统计与耗时
光看通话内容还不够,有时你想知道“哪通电话耗时最长、哪路电话打得最频繁”。每到月底,酒店会打印一份服务账单:每个服务项目被叫了多少次、累计占用了多久、失败了多少回。strace 的 -c 参数就是这张账单。
用法是 strace -c 命令,程序跑完后 strace 会输出一张汇总表,内容包括:每个系统调用的调用次数(calls)、累计耗时(seconds)、单次平均耗时(usecs/call)、耗时占比(% time)和错误次数(errors)。想更细致地看单次调用耗时,用 -T 给每条调用后面追加快耗时秒数;用 -r 则打印相对上一条调用的时间戳,适合观察调用节奏。
性能分析时推荐两步走:先 -c 看占比,找到最耗时的调用类型;再用 -T 定位具体哪一次调用异常慢。例如发现 write 占比高达 80%,往往是程序频繁小写导致系统调用开销过大,改成批量写入就能显著提速。
这张“账单”就像酒店给你列出“客房服务耗时 3 小时、叫车仅 30 分钟”,哪项服务最拖时间一目了然。性能瓶颈不会藏在代码注释里,它就写在 strace 的统计表中——占比最高的那个调用,就是你要下刀的地方。
- 分子 t_i第 i 类系统调用的累计耗时,把这类调用每次消耗的时间全部相加。
- 分母求和所有系统调用耗时之和,作为占比的基准总量。
- 百分比转换乘以 100% 得到该类调用的耗时占比,占比越大越值得优化。
实战问题排查
工具齐了,来看四个最常见的“客人投诉”案例。第一个:程序启动就报文件找不到。跑 strace -f -o log.txt ./app,然后在日志里搜 ENOENT,看到 open("config.yaml", O_RDONLY) = -1 ENOENT——原来是工作目录不对,程序根本没找到它以为存在的配置文件。路径问题的根源往往藏在相对路径里。
第二个:权限拒绝。日志中出现 EACCES,用 ls -l 检查文件属主和权限,发现运行用户不是文件属主,也没有读权限。这就像住客拿着一张别人的房卡去开门,总台当然拒绝。第三个:网络连接异常。strace -e trace=network ./client 看到 connect 返回 ECONNREFUSED,说明目标端口没人监听;返回 ETIMEDOUT,多半是防火墙丢了包。
第四个:程序卡死。这是线上最惊险的场景。strace -p <pid> 附加后,屏幕停在最后一条调用上不再前进——卡在哪就停在哪。如果是 read 等待输入,说明在等数据;如果是 futex(FUTEX_WAIT),基本可以判定锁竞争或死锁。这时再看代码里对应的锁逻辑,往往一击即中。
四个案例就像酒店的四类投诉:走错门(路径问题)、没钥匙(权限问题)、对方不接电话(网络问题)、电话占线(卡死)。有了通话录音带,每类投诉都能当场破案,不需要再猜。
- ENOENT 判断看到这个错误码,直接检查路径拼写、文件是否存在、工作目录是否正确。
- EACCES 判断看到这个错误码,检查文件权限、属主身份、SELinux 等访问控制。
- ECONNREFUSED 判断网络层被对端拒绝,检查端口监听状态和防火墙规则。
ltrace库跟踪
有时候问题出在“服务员”身上而不是“大堂经理”——比如字符串处理出错、内存悄悄膨胀。这时候需要随身记录仪 ltrace,它记录的是住客与服务员之间的日常互动,也就是库函数调用。
ltrace 的用法和 strace 几乎同构:ltrace 命令 跟踪库函数调用;-e 按函数名过滤;-c 输出统计;-p PID 附加运行进程。它显示的是 malloc、strlen、printf 这类动态库函数。一个典型的输出长这样:printf("hello") = 6,表示 printf 这个库函数被调用,返回了 6 个字符。
实战中经常两级配合:先用 ltrace 看程序调了哪些库函数,发现可疑点后再下沉到 strace 看对应的系统调用。比如 ltrace 显示 malloc 被疯狂调用且内存曲线暴涨,strace 发现底层 brk 和 mmap 频繁扩大堆区,就能顺藤摸瓜定位到内存分配失控的代码路径。
有了 strace(总台录音)和 ltrace(服务员记录仪)两套设备,从程序逻辑到内核动作全程可追溯——这就是 Linux 排障的完整监控链条。先看服务员怎么跑腿,再看总台怎么批示,任何异常行为都无处遁形。
- 库函数调用程序调用 printf,这是用户态可见的库函数,ltrace 在这一层监听。
- 内部转换glibc 负责把格式化后的数据整理成缓冲区,再交给内核接口。
- 系统调用落地write 真正把缓冲区内容写入文件描述符,strace 在这一层监听。
AI 应用场景
ML 训练脚本“找不到文件”的迷案
阶段:数据准备 / 故障诊断
解决的问题:训练脚本在 IDE 里能跑、放到定时任务就报 FileNotFoundError,日志却没给出真实路径。用 strace -f -o train.log python train.py 后在日志里搜索 ENOENT,看到 open("data/train.csv") = -1,发现调度系统的工作目录是 /root,而相对路径 data 根本不存在——这就是典型的“走错门”问题。
具体案例:某 AI 平台的定时训练任务凌晨 3 点失败,运维用 strace 定位到 open("/root/data/train.csv") 返回 ENOENT,原来是 cron 没有切换工作目录。把脚本里的相对路径改成绝对路径后,任务恢复稳定运行。
推理服务接口“慢得像蜗牛”
阶段:模型部署 / 性能分析
解决的问题:接口 P99 延迟高,应用日志看不出瓶颈。用 strace -c -p <pid> 采样后发现 read 调用占比 68%,再用 -T 看到每次 read 都只读 4KB 小数据,磁盘 IOPS 被打满——这是“账单”直接指认的瓶颈。
具体案例:某推荐系统的向量文件用单条 read 逐条加载,strace 显示 read 调用高达 12 万次/分钟。改为 mmap 内存映射后,P99 延迟从 800ms 降到 90ms,模型加载速度提升近 9 倍。
线上服务“卡死不动”的应急定位
阶段:推理服务 / 线上应急
解决的问题:服务无响应、CPU 占用低,直接重启会丢失现场。strace -p <pid> 附加后,输出停在 futex(..., FUTEX_WAIT) 不再前进,说明线程在等待锁——配合 pstack 打印线程栈,即可确认死锁链条。
具体案例:某大模型推理服务偶发假死,strace 停在 futex 等待,定位到缓存组件的锁未释放,升级版本后彻底解决。整个过程不到 10 分钟,避免了盲目重启导致的事故升级。
Python 演示
import reimport subprocess def run_strace(target_cmd): """在 strace 下运行目标命令,返回逐行原始输出.""" trace_log = "/tmp/strace_demo.log" try: subprocess.run( ["strace", "-o", trace_log, "-f", "-e", "trace=file"] + target_cmd, capture_output=True, timeout=10, ) except FileNotFoundError: print("未找到 strace,请先安装: sudo apt install strace") return [] with open(trace_log, "r", errors="ignore") as fh: return fh.readlines() def parse_calls(lines): """解析形如 open(\"/etc/hostname\", O_RDONLY) = 3 的调用行.""" pattern = re.compile(r"^(\w+)\((.*)\)\s*=\s*(-?\w+)\s*(.*)") stats = {} for line in lines: m = pattern.match(line.strip()) if not m: continue name, args, ret, extra = m.groups() item = stats.setdefault(name, {"count": 0, "errors": 0}) item["count"] += 1 if ret == "-1": item["errors"] += 1 return stats def print_report(stats): """按次数排序打印调用统计表.""" total = sum(v["count"] for v in stats.values()) print("系统调用统计:") print("%-16s %-8s %-8s %s" % ("调用名", "次数", "失败", "占比")) for name, v in sorted(stats.items(), key=lambda kv: -kv[1]["count"]): ratio = 100.0 * v["count"] / total if total else 0.0 print("%-16s %-8d %-8d %.1f%%" % (name, v["count"], v["errors"], ratio)) def main(): import sys cmd = sys.argv[1:] or ["cat", "/etc/hostname"] stats = parse_calls(run_strace(cmd)) print_report(stats) if __name__ == "__main__": main()
-c 统计能力搬进 Python,方便二次分析。["strace", "-o", trace_log, "-f", "-e", "trace=file"] + target_cmd组装 strace 命令,-f跟踪子进程,-e只保留文件类调用,减少噪音pattern = re.compile(r"^(\w+)\((.*)\)\s*=\s*(-?\w+)\s*(.*)")用正则匹配“调用名(参数) = 返回值”的标准输出格式stats.setdefault(name, {"count": 0, "errors": 0})第一次见到某调用时自动初始化计数器,避免手动判断item["count"] += 1每出现一次调用计数加一,等价于 strace -c 里的 calls 列if ret == "-1": item["errors"] += 1返回值是 -1 就记一次失败,对应 errors 列sorted(stats.items(), key=lambda kv: -kv[1]["count"])按调用次数降序排列,让最频繁的调用排在最前面ratio = 100.0 * v["count"] / total if total else 0.0计算每种调用占比,对应正文里的耗时占比公式
常见误区
误区听说 strace 用 ptrace 拦截所有系统调用,程序会慢十倍以上,线上千万不能用,用了会被领导骂。
正解strace 确实有性能开销,因为每个系统调用都要经过 ptrace 拦截,但开销并没有夸张到“慢十倍”。用 -e trace= 过滤只保留关心的调用、用 -p 短暂附加观察几秒、结束后立即分离,开销完全可控。相比盲目猜测故障原因浪费的几小时,这几十毫秒的代价非常值得。
为何常见:ptrace 机制确实会让目标进程在每次系统调用时暂停,大家以讹传讹把“有开销”放大成“不能碰”,忽略了过滤器这个救命的开关。
误区程序卡死、算错、崩溃,strace 一下就能看到全部原因,它就是程序界的监控摄像头。
正解strace 只能看到系统调用这一层——程序什么时候打开文件、读写网络、申请内存。它看不到程序内部的变量值、循环逻辑、函数调用栈。内存越界、死循环这些纯粹发生在用户态的运算,strace 是瞎的,需要配合 gdb、perf 等工具才能看清。
为何常见:初学者看到 strace 能输出大量信息,误以为“系统调用 = 程序全部行为”,其实这只是程序与内核交互的边界。
误区打开日志一看全是 `= -1 EAGAIN`,吓得赶紧重启服务,以为程序已经病入膏肓。
正解非阻塞 IO 场景下,EAGAIN 和 EWOULDBLOCK 是正常现象,表示“现在没数据,先干别的去”,程序恰恰是健康地在轮询。真正要警惕的是 ENOENT、EACCES、EPERM 这类不可重试的错误。判断标准不是“返回 -1”,而是“错误码是否致命、上下文是否合理”。
为何常见:把“调用失败”和“程序 bug”直接画等号,忽略了 errno 本身分可重试与不可重试两类,这是对错误码体系理解不透彻。
误区都是跟踪工具,名字也像,随便用一个就行,反正输出看起来差不多。
正解两者跟踪层级完全不同。strace 看的是内核边界上的系统调用,ltrace 看的是用户态的库函数调用。很多库函数压根不触发系统调用——比如 strlen 纯粹在内存里数数,strace 永远看不到它。想定位内存分配风暴要用 ltrace,想定位文件访问路径要用 strace。
为何常见:二者输出格式相似、安装方式相同,加上“工具名字长得像”,让很多人误以为只是不同的发行版。
误区程序自己会打日志,日志里写了“文件不存在”我就信它,直接去检查文件就行。
正解程序日志是程序“自己写的自白”,会隐瞒细节、甚至撒谎。比如程序报了“配置文件缺失”,但真实原因可能是它先尝试打开了一个错误的相对路径。strace 是内核视角的客观录音,能看到程序没说出口的动作——实际打开了几次、每次用的什么路径、被谁拒绝。应用日志负责告诉你“出事了”,strace 负责告诉你“到底发生了什么”。
为何常见:过度信任应用层日志,不知道有“第三方视角”的客观记录存在,这也正是 strace 最独特的价值所在。
面试题
Q1. strace 默认把跟踪结果输出到哪里?
- A.输出到标准输出设备
- B.输出到标准错误设备← 正确答案
- C.输出到系统的日志文件
- D.直接存入内核的缓冲区
答案:B。strace 默认把跟踪结果输出到标准错误流 stderr,而不是标准输出流 stdout,这是为了方便把程序的正常输出重定向走,避免监听日志污染结果。就像录音设备的“外放喇叭”不走住客常用的通道,防止干扰正常通话。C 和 D 都不符合默认行为。
Q2. 想追踪一个新启动的程序的系统调用,正确的用法是?
- A.在 strace 后面跟程序名← 正确答案
- B.用 strace -p 跟程序名
- C.把 strace 放在程序名后面
- D.用 strace --pid 跟程序名
答案:A。追踪新启动程序的用法是 strace 程序名,把目标程序直接跟在 strace 后面。-p 后面只能跟进程号 PID,不能跟程序名;把 strace 放程序名后面是错误语法;--pid 并不是 strace 的合法长选项。这就像开录音机要先放目标“磁带”一样,命令顺序决定了监听对象。
Q3. 要附加到 PID 为 2024 的正在运行进程进行跟踪,应使用?
- A.使用 strace 2024 进程号
- B.使用 strace -p 2024 进程号← 正确答案
- C.使用 strace -f 2024 进程号
- D.使用 strace -a 2024 进程号
答案:B。附加到已运行进程必须用 -p PID 参数,适合线上程序卡死时“临时接上录音”。strace 2024 会把 2024 当成程序名去执行而报错;-f 是跟踪子进程,不是附加;-a 不是合法选项。记住核心口诀:新程序直接跟,老进程用 -p。
Q4. 想统计程序各系统调用的次数和耗时占比,应使用哪个参数?
- A.使用 strace -c 统计汇总← 正确答案
- B.使用 strace -T 逐次计时
- C.使用 strace -r 精度计时
- D.使用 strace -s 输出截断
答案:A。-c 会在程序结束后输出汇总表,包含每个系统调用的次数、累计耗时和耗时占比,是性能分析的首选。-T 是给每条调用追加耗时,-r 是相对时间戳,-s 控制字符串截断长度。就像酒店月底打印服务账单,-c 直接给你“哪项服务最耗时”的结论。
Q5. 关于 strace -e trace=open,read 的说明,正确的是?
- A.只显示 open 和 read 两种调用← 正确答案
- B.open、read 之外的调用被忽略← 正确答案
- C.等效于跟踪 file 类别全部调用
- D.同时启用调用统计汇总模式
答案:AB。-e trace=open,read 是白名单过滤,只显示 open 和 read 两个系统调用,其他调用一律不显示,所以 A 和 B 正确。它不等同于 trace=file——file 类别包含更多文件相关调用;也不会启用统计,统计需要单独的 -c 参数。这就像给录音机设了关键词,只保留你关心的通话。
Q6. strace 输出 open("/a.txt", O_RDONLY) = -1 ENOENT,说明什么?
- A.打开成功且描述符为 -1
- B.文件不存在导致打开失败← 正确答案
- C.文件无读权限被拒绝
- D.文件被其它进程占用中
答案:B。ENOENT 是 “No such file or directory“ 的缩写,表示文件或目录不存在,打开操作失败。权限不足会返回 EACCES,文件被占用通常返回 EAGAIN 或 EBUSY。就像电话里听到”您拨打的号码是空号”,ENOENT 就是告诉你这个路径根本不存在。
Q7. ltrace 与 strace 跟踪层级的关键区别是?
- A.ltrace 跟踪库函数而非系统调用← 正确答案
- B.ltrace 跟踪系统调用而非库函数
- C.ltrace 只能应用于编译型语言
- D.ltrace 能查看函数内部的计算
答案:A。ltrace 跟踪的是动态库函数调用(如 printf、malloc),发生在用户态;strace 跟踪的是系统调用,发生在内核边界。二者层级不同,不能互相替代。ltrace 并不局限于编译型语言,也看不到函数内部的计算过程——它只记录“调用了谁”。
Q8. 线上服务无响应时,用 strace 定位卡顿点的合理做法是?
- A.用 strace -p 附加进程观察← 正确答案
- B.看最后一条调用是否阻塞← 正确答案
- C.立即杀掉进程再重启观察
- D.用 ltrace 查看内核侧状态
答案:AB。定位卡死要先用 strace -p 附加观察,屏幕停在哪个系统调用上,就说明卡在哪里——比如停在 futex 是等锁,停在 read 是等数据。杀掉重启会丢失现场,属于最后的兜底手段而非定位手段;ltrace 看的是库函数,不是内核状态。先录下“卡住的那一帧”,才能对症下药。
Q9. strace 的 -f 选项起什么作用?
- A.跟随子进程一并跟踪← 正确答案
- B.表示只跟踪文件类调用
- C.强制以管理员身份运行
- D.输出完整的不截断参数
答案:A。-f(follow)让 strace 同时跟踪 fork、exec 出来的子进程。多进程程序(如 nginx、Java 应用)如果不加 -f,只能看到主进程的调用,子进程的“通话”全部漏掉。它不负责文件过滤、权限提升或参数截断,那些是 -e、sudo、-s 的职责。
Q10. 关于 strace -c 汇总表中 calls 列的解读,正确的是?
- A.记录该调用的调用总次数← 正确答案
- B.包含返回错误的调用计数← 正确答案
- C.表示该调用的累计消耗时间
- D.表示每秒完成的调用数量
答案:AB。-c 汇总表中的 calls 列是该系统调用被调用的总次数,既包含成功的调用也包含返回错误的调用(错误数单独显示在 errors 列),所以 A 和 B 正确。累计耗时对应 seconds 列,每秒调用数量不是 strace 的标准输出列。读懂这一列,才能正确判断“哪个调用最频繁”与“哪个调用最耗时”是两个不同维度的瓶颈。