Android启动时间优化大全

1 修改Android mksh默认的列长度
不修改这个参数,adb shell后,输入超过80个字符,就不能看到完整的命令行

@ external/mksh/src/sh.h
EXTERN mksh_ari_t x_cols E_INIT(80);    /* tty columns */
EXTERN mksh_ari_t x_lins E_INIT(24);    /* tty lines */

2 内核模块ko签名问题
2.1 内核配置
CONFIG_MODULE_SIG=y
- 表示开启了签名机制,但是这时候模块签名或不签名都可以使用。

CONFIG_MODULE_SIG_FORCE=y
- 如果上述配置项使能,则模块必须有正确的签名才能正常使用。

CONFIG_MODULE_SIG_ALL=y
- 内核在编译的时候,并不会主动去给模块签名,除非你把上述配置项打开。

@ kernel/kernel/Makefile
其中,x509.genkey是生成key pair时的配置项,signing_key.priv、signing_key.x509分别为private key和数字证书。数字证书会打包进内核,里面有公钥等,用来解密。每编译一次,虽然配置文件每次都相同,但是生成的key pair是不同的。

2.2 Linux ko模块编译脚本
2.2.1 QCOM
@ device//common/dlkm/AndroidKernelModule.mk

2.2.2 OEM
@ hello.c

@ Makefile
#no-pic:Position Independent Code, 位置无关代码
obj-m := hello.o

PREFIX=Android源码路径-LINUX/android
KERNELDIR := $(PREFIX)/out/target/product//obj/KERNEL_OBJ/
PWD :=$(shell pwd)
ARCH=arm
CROSS_COMPILE=$(PREFIX)/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-

CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
CFLAGS_MODULE=-fno-pic

modules:
    make -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
clean:
    rm *.o *.ko *.mod.c *.order *.symvers

3 vbmeta
3.1 vbmeta.img生成工具
/external/avb/avbtool
Android编译脚本使用该python工具,参数包括boot.img、system.img、vendor.img等,生成vbmeta.img

3.2 AVB工作流程
需要提前挂载分区的fstab来自于commandline的androidboot.android_dt_dir

1)bootloader使用内置的OEM pubk验证vbmeta.img,验证通过后用vbmeta.img中的boot pubk验证boot.img,如果验证通过就启动boot.img
2)init启动后,init/fs_mgr使用vbmeta.img中的vendor pubk、system pubk、odm_pubk验证vendor.img、system.img、odm.img,验证通过就mount,否则不会mount

3.3 AndroidO userdebug版本运行时禁止dm-verity
AndroidO dm-verity disable flag存在于vbmeta.img(keystore分区)中;而老版本是放置在system.img分区的dm-verity metadata中。
1)在设置中打开OEM unlocking选项
2)在设置中打开USB debugging选项
3)adb reboot bootloader
4)fastboot flashing unlock和fastboot oem unlock
5)fastboot reboot
6)adb root
7)adb disable-verity
8)adb reboot
9)adb root
10)adb remount

3.4 AndroidO userdebug版本刷机时禁止dm-verity
AndroidO dm-verity disable flag存在于vbmeta.img(keystore分区)中;而老版本是放置在system.img分区的dm-verity metadata中。
1)在设置中打开OEM unlocking选项
2)在设置中打开USB debugging选项
3)adb reboot bootloader
4)fastboot flashing unlock和fastboot oem unlock
5)fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img
6)fastboot reboot
7)adb root
8)adb remount

4 Kernel优化
4.1 内核模块ko化
将内核中尽可能多的驱动模块化,写一个负责insmod的shell脚本,开机时作为服务运行,可以大大减少内核启动的时间。同时由于init后是多任务运行,脚本服务对init启动其它服务的延时可以忽略不计。

注意insmod是阻塞调用,所以直接在init.rc脚本中调用,还是会加长启动时间,所以需要insmod的模块统一放到一个脚本服务中。

@ BoardConfig.mk
BOARD_VENDOR_KERNEL_MODULES
BOARD_RECOVERY_KERNEL_MODULES

4.2 提升console串口的波特率

4.3 Printk
4.3.1 实现原理
printk的实现原理很简单,在有了日志消息后,首先申请控制台的信号量,如果申请到,则调用控制台写方法,写控制台。

在内核源码树的kernel/printk.c中,使用宏DECLARE_MUTEX声明了一个互斥锁console_sem,他用于保护console驱动列表console_drivers及同步对整个console驱动系统的访问。其中定义了函数acquire_console_sem来获得互斥锁console_sem,定义了release_console_sem来释放互斥锁console_sem,定义了函数try_acquire_console_sem来尽力得到互斥锁console_sem。这三个函数实际上是分别对函数down,up和down_trylock的简单包装。需要访问console_drivers驱动列表时就需要使用acquire_console_sem来保护console_drivers列表,当访问完该列表后,就调用release_console_sem释放信号量console_sem。函数console_unblank,console_device,console_stop,console_start,register_console 和unregister_console都需要访问console_drivers,因此他们都使用函数对acquire_console_sem和release_console_sem来对console_drivers进行保护。

调试console_sem时,需要打开宏CONFIG_DEBUG_SPINLOCK以跟踪owner字段。

关闭Kernel Log,通过bootchart.png可以看到启动init进程的时间明显提前,可以加快启动速度。
@ kernel/printk.c
int console_printk[4] = {
    DEFAULT_CONSOLE_LOGLEVEL,   /* console_loglevel */
    DEFAULT_MESSAGE_LOGLEVEL,   /* default_message_loglevel */
    MINIMUM_CONSOLE_LOGLEVEL,   /* minimum_console_loglevel */
    DEFAULT_CONSOLE_LOGLEVEL,   /* default_console_loglevel */
};
改为
int console_printk[4] = {
    0, //DEFAULT_CONSOLE_LOGLEVEL,  /* console_loglevel */
    0, //DEFAULT_MESSAGE_LOGLEVEL,  /* default_message_loglevel */
    0, //MINIMUM_CONSOLE_LOGLEVEL,  /* minimum_console_loglevel */
    0, //DEFAULT_CONSOLE_LOGLEVEL,  /* default_console_loglevel */
};
这四个值对应到路径proc/sys/kernel/printk,当printk()没有指定消息级别时,就采用DEFAULT_MESSAGE_LOGLEVEL(对应到KERN_WARNING = 4)。

echo "8 8 8 8" > /proc/sys/kernel/printk
- 第一个“8”表示内核打印函数printk的打印级别

4.3.2 pr_debug动态log
CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y

echo "file my_drv.c +p" > /sys/kernel/debug/dynamic_debug/control

4.3.3 kernel调试时打开所有log
BOARD_KERNEL_CMDLINE += ignore_loglevel

动态修改:
echo 0 > /sys/module/printk/parameters/ignore_loglevel
echo 1 > /sys/module/printk/parameters/ignore_loglevel

4.4 调试驱动probe耗时
@ BoardConfig.mk
BOARD_KERNEL_CMDLINE += initcall_debug ignore_loglevel

5 Init
5.1 Sections Loading Sequence
on early-init
wait_for_coldboot_done()
on init
on early-fs
on fs
on post-fs
on post-fs-data
on early-boot
on boot

5.2 Init Log机制
无论init代码架构如何变化,init进程的log始终是通过/dev/kmsg输出。
@ system/core/base/logging.cpp

@ system/core/init/action.cpp
void ActionManager::ExecuteOneCommand() {
    [...]
    有打印处理每个action开始的log到/dev/kmsg,可以用来查看处理时间
    [...]
}

自定义kmsg函数:
#include
#include
#include
#include
#include
static void kmsg(const char *fmt, ...)
{
    char buf[512] = {0};
    va_list ap;
    int n, flags;
    static int fd = 0;
    
    va_start(ap,fmt);
    n = vsnprintf(buf, 511, fmt, ap);
    va_end(ap);
    
    if (fd <= 0) {
        fd = open("/dev/kmsg", O_RDWR);
        if (fd > 0) {
            // 必须加,否则init fork zygote后,该描述符会被zygote继承,导致zygote异常,不断重启
            flags = fcntl(fd, F_GETFD);
            flags |= FD_CLOEXEC;
            fcntl(fd, F_SETFD, flags);
        }
    }
    
    if ((fd > 0) && (n > 0)) {
        write(fd, buf, n);
    }
}

如果往/dev/kmsg中写log,通过dmesg几乎看不到log,那么加上如下的配置
@ BoardConfig.mk
BOARD_KERNEL_CMDLINE += printk.devkmsg=on

该配置用在如下的代码中:
@ kernel/printk/printk.c
devkmsg_write()

6 IO
6.1 CPU手动调频
@ /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Foreground:Tasks run all cores
Background:Tasks run little cores
System-background:Tasks run all little cores for system processes that shouldn’t run on big cores
TOP-APP:Tasks run all cores big cores
​​​​​​
6.2 eMMC5.1速度调试
6.2.1 速度调试
eMMC5.1支持的速度模式:DDR50、HS200 SDR、HS200 DDR(也叫HS400),代码中的配置如下例所示。
@ drivers/mmc/host/sdhci-pci-core.c
caps:MMC_CAP_1_8V_DDR
caps2:MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR

eMMC DTR低速的工作电压是3.3V,高速1.8V。类似于USB,低速全速DPDM是3.3V,高速DPDM是400mV。

@ drivers/mmc/core/mmc.c
mmc_attach_mmc(struct mmc_host *host);  - eMMC异常时需要debug该函数
mmc_select_driver_type(struct mmc_card *card); - 设置驱动能力MMC_SET_DRIVER_TYPE_A{C/D}等类型

6.2.2 eMMC卡调试路径
/sys/class/mmc_host/mmcN/mmcN:00001
/sys/kernel/debug/mmcN

6.2.3 eMMC用户分区挂载路径
第一次挂载路径:
/mnt/media_rw/

第二次挂载路径(使用mount的bind方式):
/mnt/runtime/default
/mnt/runtime/read
/mnt/runtime/write

6.3 IO调度Tunning
IO调度算法种类:cfq、deadline、noop(No Operation,电梯调度算法)

6.3.1 方法1
@ init.rc
on late-fs
# boot time fs tune for UFS, change sda for eMMC
    write /sys/block/sda/queue/iostats 0
    write /sys/block/sda/queue/read_ahead_kb 2048
    write /sys/block/sda/queue/nr_requests 256

    write /sys/block/dm-0/queue/read_ahead_kb 2048
    write /sys/block/dm-1/queue/read_ahead_kb 2048

on property:sys.boot_completed=1
    write /sys/block/dm-0/queue/read_ahead_kb 512
    write /sys/block/dm-1/queue/read_ahead_kb 512

    write /sys/block/sda/queue/read_ahead_kb 128
    write /sys/block/sda/queue/nr_requests 128

更好的方法是用(与上面的方法互斥):ioprio rt
添加方法如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    [...]
    # nice的取值范围是-20到+19,-20优先级最高,+19最低
    priority -20
    # 范围从0到7,数字越小ioprio real-time优先级越高
    ioprio rt 2
    [...]

6.3.2 方法2 - ionice
ionice可以用来调整特定进程的ioprio

0 - none, 1 - Realtime, 2 - Best-effort, 3 - idle
SYS_ioprio_get
SYS_ioprio_set

7 Framework优化
7.1 设置log等级环境变量
7.1.1 全局生效
设置log等级环境变量:ANDROID_LOG_TAGS
全部打开
export ANDROID_LOG_TAGS="*:v"
全局过滤
export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D * :S"

logcat :D *:S &

7.1.2 per-tag
setprop log.tag. DEBUG
@ /data/local.prop

logcat :D *:S &

7.2 Android虚拟按键编码头文件
@ framework/native/include/android/keycodes.h

7.3 Zygote
7.3.1 Preface
@ frameworks/base/cmds/app_process
@ frameworks/base/core/jni/AndroidRuntime.cpp - LOG_BOOT_PROGRESS_START
@ frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

当64位zygote启动时,它会从/data/dalvik-cache/arm64/system@framework@boot*.{art,oat,vdex}加载代码,这些被加载的jar包由环境变量BOOTCLASSPATH指定。

测试zygote c++时间:
#include
uptimeMillis()

7.3.2 preloaded-classes
@ frameworks/base/preloaded-classes

@ frameworks/base/tools/preload/WritePreloadedClassFile.java
@ frameworks/base/tools/preload/Compile.java

以上2个文件的修改,需要重新生成preload.jar
mmm frameworks/base/tools/preload/
产生文件out/host/linux-x86/framework/preload.jar

重新生成preloaded-classes文件
rm frameworks/base/preloaded-classes
rm out/target/product//system/etc/preloaded-classes
java -Xss512M -cp out/host/linux-x86/framework/preload.jar  WritePreloadedClassFile frameworks/base/tools/preload/20100223.compiled
make systemimage -j8

7.3.3 framework-res.apk
on post-fs-data
    # exec [ [ [ ]* ]] -- [ ]*
    exec u:r:init:s0 -- /system/bin/cat /system/framework/framework-res.apk > /dev/null

or

service preload_res /system/bin/cat /system/framework/framework-res.apk > /dev/null
    class core
    user root
    # 加seclabel是为了避免写cat.te文件,可以快速测试,最终提交版本是需要写cat.te的
    seclabel u:r:init:s0
    oneshot
    disabled

on post-fs-data
    start preload_res

7.3.4 多线程做preload优化
new Thread(new Runnable() {
    @Override
    public void run() {
        // TODO, call preload();
    }
}).start();

7.4 system_server
7.4.1 PMS包扫描
scanDirLI() :scanDir Lock mInstallLock

@ /system/app
@ /system/framework
@ /data/app
@ /data/app-private

Android8.0后存储管理类是StorageManagerService.java

7.4.2 Pre-optimization
编译时为apk生成*.odex和*.vdex文件

1)打开编译选项
@ BoardConfig.mk
WITH_DEXPREOPT := true
#DONT_DEXPREOPT_PREBUILTS := true

这样整个system就会被预先优化,由于在启动时不再需要对app的dex文件进行优化(事实上第一次启动时dex2oat根据pm.dexopt.first-boot的值,仍然会做少量的优化,只是时间大大缩短),从而提升其启动速度;但是其副作用就是system镜像变得比较大。

2)优化刷机后第一次启动所需的时间
属性文件路径:
vendor/default.prop
vendor/build.prop

build/下属性的配置:
--compiler-filter=speed - 系统编译时使用
pm.dexopt.first-boot=verify - 系统第一次启动时dex2oat工具使用
这2个属性的修改,可以让第一次开机快10秒左右。

3)附加配置 - 可选
如果上一步的修改不生效,抓取logcat log分析,确认log中第一次开机后仍然进行了dex2oat操作,需要对预置apk的Android.mk进行修改。

- 对于64bit的芯片,若apk只有32bit的lib或者只能作为32bit运行,预置apk时在Android.mk中添加下边的TAG,标记此apk为32bit
    LOCAL_MULTILIB :=32
- 而对于有源码无lib库的apk,注释掉Android.mk中的
    LOCAL_MULTILIB :=32
- 开机之后既提取arm又提取arm64的apk,在Android.mk中设定
    LOCAL_MULTILIB :=both

7.4.3 enableScreenAfterBoot
@ ActivityManagerService.java
enableScreenAfterBoot()
- >
@ WindowManagerService.java
enableScreenAfterBoot()
- >
mPolicy.systemBooted()  - 在PhoneWindowManager.java(PWM)中
->
performEnableScreen()
- >
checkWaitingForWindows() - 系统将检查目前所有的window是否画完,如果所有的window(包括keyguard、wallpaper和launcher等)都已经画好,系统会设置属性service.bootanim.exit值为1,退出动画。

查看当前top窗口:
findFocusedWindow()
adb shell dumpsys window windows | grep mCurrent
adb shell pm path

7.5 查看系统安装的所有APK
pm list packages

7.6 settings数据库读写
settings list system
settings put system screen_brightness 50

8 Dalvik
Android Go在data分区填近满后不能启动bug分析
http://tjtech.me/analyze-boot-failed-when-full-data-part-under-android-go.html

9 进程调试
9.1 进程优先级
mount -t cpuset cpuset /dev/cpuset
/proc/sys/kernel/sched_rr_timeslice_ms用来指示round robin调度进程的间隔,这个间隔默认是100ms。

查看进程优先级
top -d 5
top -d 5 -p

9.2 跟踪init进程和模块的调用过程
strace -T -p 1 -t
strace insmod system/lib/modules/wlan.ko
strace -e trace=read,open test

9.3 Strace Zygote
9.3.1 Android O之前
change
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
to
service zygote /system/xbin/strace -tt -o /data/zygote.strace /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    [...]
    # nice的取值范围是-20到+19,-20优先级最高,+19最低
    priority -20
    # 范围从0到7,数字越小ioprio real-time优先级越高
    ioprio rt 2  
    [...]

9.3.2 Android O - 修改init进程
@ system/core/init/service.cpp
static void trace_zygote64(pid_t pid)
{
    char pid_str[16] = {0};
    
    if (fork() == 0) {
        snprintf(pid_str, 15, "%d", pid);
        execl("/system/xbin/strace", "strace",
                "-p", pid_str,
                /*"-e", "trace=open,read,write,ioctl",*/
                "-o", "/dev/z_tr.log",
                "-s", "128",
                "-tt", "-T", "-x", NULL);
    }
}
将该函数放在创建zygote的地方。

z_tr.log中有具体时间,与logcat -b events | grep boot_progress抓取的log的关键事件时间戳进行对比,找出问题。

9.4 busybox
https://busybox.net/downloads/binaries/1.28.1-defconfig-multiarch/

查看进程树
busybox pstree

9.5 Linux signal
查看Linux支持的signal:kill -l

9.6 Linux swap分区的使用
/dev/block/zram0
procrank
free -m

9.7 strace监视文件读写
抓取unix domain socket数据的读写 - 类似于tcpdump抓取网络数据包
strace -e read=7 -e write=7 -p 1
PID为1的进程中,dump出所有对fd = 7的读写数据

9.8 Android性能分析工具汇总
top
free -m
procrank
vmstat 1
pidstat -w 1
mpstat -P ALL 3
iostat
logcat -b events | grep am_crash
logcat | grep died

https://github.com/zhenggaobing/pidstat

10 时间测量方法
10.1 Bootchart源码下载编译
http://www.bootchart.org/download.html

在Linux桌面机器上:
apt-get install ant

解压下载的bootchart源代码,在bootchart源代码目录下执行ant,结束后,产生bootchart.jar,可以在Linux上分析,也可以将该jar包拷贝到Windows上

10.2 如何使用Bootchart
Android的bootchart时间轴是从kernel启动的时间点开始计算的,这个可以根据生成的bootchart.png和kernel msg得出结论

10.2.1 AndroidM
CONFIG_DEBUG_USER=n

@ bootchart.c
/* cat /proc/devices */
#define LOG_ROOT  "/data/bootchart"
改为:
#define LOG_ROOT  "/dev/bootchart"

强制给timeout赋值:timeout = 120

touch system/core/init/bootchart.c
touch system/core/init/init.c
export INIT_BOOTCHART=true
make bootimage -j4
刷机后,重启

adb shell
skip the following two lines
mkdir /data/bootchart
echo 80 > /data/bootchart-start

logs under /dev/bootchart
cd /dev/bootchart
busybox tar zcvf bootchart.tgz header kernel_pacct proc_diskstats.log proc_ps.log proc_stat.log
adb pull /dev/bootchart/bootchart.tgz .
java -jar bootchart.jar .\bootchart.tgz

10.2.2 AndroidO
echo 1 > /data/bootchart/enabled
重启手机

logs under /data/bootchart
cd /data/bootchart
busybox tar zcvf bootchart.tgz header kernel_pacct proc_diskstats.log proc_ps.log proc_stat.log
adb pull /data/bootchart/bootchart.tgz .
java -jar bootchart.jar .\bootchart.tgz

10.3 比较修改
@ system/core/init/compare-bootcharts.py

将2次生成的bootchart.tgz分别放到old_dir和new_dir中:
python compare-bootcharts.py old_dir new_dir

10.4 perfboot
@ system/core/init/perfboot.py

将system/core/init/perfboot.py和development/python-packages/adb文件夹拷贝到同一个目录下。需要注意的是,拷贝的是adb文件夹,不然perfboot.py中的import adb会报错。生成的.tsv文件使用excel打开。

python perfboot.py --iterations=2 --interval=30 -v --output=D:\data.tsv

等价于如下的命令:
adb logcat -b events | grep boot_progress

10.5 Kernel启动时间分析
packages/services/Car/tools/bootanalyze/bootanalyze.py
packages/services/Car/tools/bootanalyze/config.yaml

10.6 获取Android各阶段的时间消耗
Android 7.0以后,init.rc除了根目录下的,还有一些业务被分拆到如下的三个目录中:
/system/etc/init
/vendor/etc/init
/odm/etc/init

dmesg | grep processing

查看bootloader启动消耗的时间,单位是毫秒:getprop ro.boot.boottime
查看service何时启动,单位是纳秒:getprop ro.boottime.
查看ueventd启动完成需要的时间,单位纳秒:getprop ro.boottime.init.cold_boot_wait

getprop | grep -i boottime
logcat | grep -i Timing

10.7 Android systrace使用
1) atrace.rc
打开默认关闭的trace开关
@ frameworks/native/cmds/atrace/atrace.rc 
- write /sys/kernel/debug/tracing/tracing_on 0
+ #write /sys/kernel/debug/tracing/tracing_on 0

2) 附加配置
@ device//common/common.mk
PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922

@ BoardConfig.mk
BOARD_KERNEL_CMDLINE += trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug,block,ext4

3) 开机完成后结束纪录
项目的init..rc文件加入如下修改,目的是结束trace记录。
on property:sys.boot_completed=1
    write /d/tracing/tracing_on 0
    write /d/tracing/events/ext4/enable 0
    write /d/tracing/events/block/enable 0

4) 抓取log并分析
做完上述修改后编译烧录镜像文件,待开机结束后执行:
adb root
adb shell "cat /d/tracing/trace" > boot_trace

然后执行
python external/chromium-trace/systrace.py --from-file=boot_trace -o boot_trace.html
上述命令可以将trace log转成html文件,用浏览器打开即可。

11 workqueue
@ kernel/workqueue.c
static int worker_thread(void *__worker)

- 对于create_singlethread_workqueue()而言,即使是对于多CPU系统,内核也只负责创建一个worker_thread()内核进程
- create_workqueue(),对于多CPU系统而言,对每一个CPU,都会生成一个新的worker_thread()进程
- schedule_delayed_work()和schedule_work()对应到默认线程events/X

12 Abbreviations
bzImage:big zImage
vmlinuz:virtual memory
ABS_MT_POSITION_X:Multi Touch
Android PMS LI、LIF、LPw、LPr:要想弄明白方法名中的LI、LIF、LPw、LPr的含义,需要先了解PackageManagerService内部使用的两个锁。因为LI、LIF、LPw、LPr中的L,指的是Lock,而后面跟的I和P指的是两个锁,I表示mInstallLock同步锁;P表示mPackages同步锁。LPw、LPr中的w表示writing,r表示reading。LIF中的F表示Freeze。
avb:Android Verified Boot,用dm-verify验证system分区的完整性,用在Android 8.0之后的fstab文件中
scanDirLI() :scanDir Lock mInstallLock
APUE:əˈpju,Advanced Programming in the UNIX Environment
AT_FDCWD:File Descriptor Current Working Directory
bail out:跳伞
BLCR:BerkeleyLab Checkpoint/Restart
FRP:Factory Reset Protection
Intercept:API拦截,通信拦截
Linux dd命令:if表示input file,of表示output file,bs表示block size
Linux EPROTO:表示USB bitstuff出现了错误,眼图有问题
lmkd:Low Memory Killer Daemon
lsof:list open files
MIDR:ARM Main ID Register
MPIDR:ARM MultiProcessor ID Register
PPID:Parent Process ID(Linux ps命令可以看到),MFi:Product Plan ID
PuTTY:ˈpʌti
RA:Linux blockdev read ahead
Slog.wtf:what a terrible failure
USB BH reset:Bigger Hammer or Brad Hosler,表示warm reset;you may be confused why the USB 3.0 spec calls the same type of reset "warm reset" in some places and "BH reset" in other places. "BH" reset is supposed to stand for "Big Hammer" reset, but it also stands for "Brad Hosler". Brad died shortly after the USB 3.0 bus specification was started, and they decided to name the reset after him. The suggestion was made shortly before the spec was finalized, so the wording is a bit inconsistent.

你可能感兴趣的:(System)