| <html devsite><head> |
| <title>使用 strace</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p>通过 <a href="https://strace.io">strace</a>,您可以看到进程执行的系统调用,以及这些系统调用返回的内容。通常情况下,一次进程会执行大量系统调用,因此您需要查看 <a href="http://man7.org/linux/man-pages/man1/strace.1.html">strace 手册页面</a>,了解如何只收集您真正感兴趣的数据。</p> |
| |
| <h2 id="build-strace">构建 strace</h2> |
| |
| <p>要构建 strace,请运行以下命令:</p><pre> |
| $ mmma -j6 external/strace |
| </pre> |
| |
| <h2 id="attach-strace">附加到正在运行的进程</h2> |
| |
| <p>对于 strace,最简单和最常见的用例即是附加到正在运行的进程,方法是使用下面这行命令:</p> |
| <pre> |
| $ adb shell strace -f -p PID |
| </pre> |
| <p><code>-f</code> 标记表明 strace 会附加到相应进程中的所有现有线程,以及之后会产生的所有新线程。</p> |
| |
| <h2 id="app-strace">在应用上使用</h2> |
| <p>要在应用上使用 strace,请执行以下操作:</p> |
| |
| <ol> |
| <li>为 strace 日志设置一个目录:<pre> |
| $ adb shell setenforce 0 |
| $ adb shell mkdir /data/local/tmp/strace |
| $ adb shell chmod 777 /data/local/tmp/strace |
| </pre> |
| </li> |
| |
| <li>在启动前选择要跟踪的进程:<pre> |
| $ adb shell setprop wrap.com.google.android.browser "logwrapper strace -f -o /data/local/tmp/strace/strace.com.google.android.browser.txt" |
| </pre> |
| </li> |
| <li>正常启动该进程。</li> |
| </ol> |
| |
| <h2 id="zygote-systrace">在 zygote 上使用</h2> |
| <p>要在 zygote 上使用 strace,请修复相关的 <code>init.rc</code> zygote 行(需要使用 <code>adb shell setenforce 0</code>):</p> |
| |
| <pre> |
| $ cd system/core/ |
| $ patch -p1 <<EOF |
| --- a/rootdir/init.zygote32.rc |
| +++ b/rootdir/init.zygote32.rc |
| @@ -1,4 +1,4 @@ |
| -service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server |
| +service zygote /system/xbin/strace -o /data/local/tmp/zygote.strace /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server |
| class main |
| socket zygote stream 660 root system |
| onrestart write /sys/android_power/request_state wake |
| EOF |
| </pre> |
| |
| <h2 id="get-logs-boot">获取 Android 启动期间的 strace 日志</h2> |
| |
| <p>要获取 Android 启动期间的 strace 日志,请执行以下更改:</p> |
| |
| <ul> |
| <li>由于进程名称已从 <code>zygote</code> 改为 <code>strace</code>,给定服务可能会因缺少用于 <code>strace</code> 的 SELinux <code>file_context</code> 而无法启动。解决方法:在 <code>system/sepolicy/private/file_contexts</code> 中为 strace 添加一个新行,并将原始文件上下文复制过来。例如:<pre> |
| /dev/socket/zygote u:object_r:zygote_socket:s0 |
| + /system/xbin/strace u:object_r:zygote_socket:s0 |
| </pre> |
| </li> |
| |
| <li>添加内核命令,然后在 SELinux 宽容模式下启动相应设备。为此,请将 <code>androidboot.selinux=permissive</code> 添加到 <code>BOARD_KERNEL_CMDLINE</code>。(该变量在 <code>build/core/Makefile</code> 中将会变为仅供读取,但在 <code>/device/*/BoardConfig</code> 下则是始终可用。) |
| |
| <br /> |
| <br /><code>/device/google/marlin/sailfish/BoardConfig.mk</code> 中 Pixel (sailfish) 设备的示例:<pre> |
| - BOARD_KERNEL_CMDLINE := .... androidboot.hardware=sailfish ... |
| +BOARD_KERNEL_CMDLINE := .... androidboot.hardware=sailfish ... androidboot.selinux=permissive |
| </pre>待做出上述更改后,编译并刷写启动映像;这样一来,该设备便会在宽容模式下启动了。 |
| </li> |
| </ul> |
| |
| </body></html> |