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

external/mksh/src/sh.h
EXTERN mksh_ari_t x_cols E_INIT(80);
EXTERN mksh_ari_t x_lins E_INIT(24);

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

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

BoardConfig.mk
BOARD_VENDOR_KERNEL_MODULES
BOARD_RECOVERY_KERNEL_MODULES

2.2 提升console串口的波特率

2.3 printk
2.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,
DEFAULT_MESSAGE_LOGLEVEL,
MINIMUM_CONSOLE_LOGLEVEL,
DEFAULT_CONSOLE_LOGLEVEL,
};
改为
int console_printk[4] = {
0, //DEFAULT_CONSOLE_LOGLEVEL,
0, //DEFAULT_MESSAGE_LOGLEVEL,
0, //MINIMUM_CONSOLE_LOGLEVEL,
0, //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的打印级别

2.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

2.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

2.4 调试驱动probe耗时
BoardConfig.mk
BOARD_KERNEL_CMDLINE += \
initcall_debug ignore_loglevel

3 Android init进程
3.1 init
stage1: device tree
stage2: fstab

3.2 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

3.3 init Log机制
无论init代码架构如何变化,init进程的log始终是通过/dev/kmsg输出。
android::base::InitLogging(argv,
&android::base::KernelLogger);

LOG:普通的流式
PLOG:普通的流式,但是可以打印错误,类似于Linux的perror()

3.4 自定义kmsg函数
#include <sys/stat.h>
#include <sys/types.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
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()

4 IO
4.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

4.2 eMMC5.1速度调试
Read my blog “Flash闪存技术”。

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

4.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 <value>
添加方法如下:
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
[...]
Read my blog “Linux Containers知识点”。

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

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

5 Framework优化
5.1 设置log等级
/data/local.prop
setprop log.tag.<tagname> VERBOSE
setprop persist.log.tag.<tagname> VERBOSE

5.2 Android虚拟按键编码头文件
frameworks/native/include/android/keycodes.h

5.3 Zygote
5.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<utils/SystemClock.h>
uptimeMillis()

5.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/<ppp>/system/etc/preloaded-classes
java -Xss512M -cp out/host/linux-x86/framework/preload.jar  WritePreloadedClassFile frameworks/base/tools/preload/20100223.compiled
make systemimage -j8

5.3.3 framework-res.apk
on post-fs-data
# exec [ <seclabel> [ <user> [ <group> ]* ]] -- <command> [ <argument> ]*
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

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

5.4 system_server
5.4.1 PMS包扫描
scanDirLI() :scanDir Lock mInstallLock

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

Android 8.0后存储管理类是StorageManagerService.java

5.4.2 Pre-optimization
Android第一次开机后会进行dex2oat操作。

5.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 <package name>

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

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

6 进程调试
6.1 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

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

查看进程树
busybox pstree

show threads
busybox ps -T
busybox top -H

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

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

6.5 strace zygote
修改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的关键事件时间戳进行对比,找出问题。

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

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

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

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

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

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

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

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

7.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

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

7.6 获取Android各阶段的时间消耗
getprop | grep -i boottime
logcat | grep -i Timing

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

2) 附加配置
in device/<OEM>/common/common.mk
PRODUCT_PROPERTY_OVERRIDES += \
debug.atrace.tags.enableflags=802922

in 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.<PRODUCT>.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文件,用浏览器打开即可。

8 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/90892.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90892.shtml
英文地址,请注明出处:http://en.pswp.cn/web/90892.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matplotlib.pyplot: 底层原理简析与进阶技巧

文章目录 1 底层实现原理 1.1 核心架构 1.1 渲染流程 2 基础用法 2.1 基本绘图 2.2 多子图系统 2.3 高阶用法 2.3.1 自定义Artist对象 2.3.2 高级动画技术 2.3.3 事件处理系统 2.3.4 混合渲染技术 3 性能优化技巧 4 扩展模块 5 总结 5.1 底层原理关键点 5.2 进阶技巧 1 底层实现…

深入理解现代前端开发中的 <script type=“module“> 与构建工具实践

引言&#xff1a;模块化开发的演进在早期的前端开发中&#xff0c;JavaScript 缺乏原生的模块化支持&#xff0c;开发者不得不依赖 IIFE&#xff08;立即调用函数表达式&#xff09;或第三方库&#xff08;如 RequireJS&#xff09;来实现代码组织。随着 ES6&#xff08;ES2015…

yolo--qt可视化开发

qt5可能不支持我们的cuda版本&#xff0c;改用qt6 YOLO11QT6OpencvC训练加载模型全过程讲解_yolov11 模型转换成opencv c模型-CSDN博客 下面是qt5版本的案例&#xff0c;和yolo及cuda有冲突 安装qt 切换到虚拟环境&#xff0c;例如pyqt&#xff0c;conda activate pyqt pip …

SQL性能优化

show [session|global] status : 查看服务器状态 show global status like Com_ : 查看各种语句的执行次数 开启慢查询: 在 MySQL 配置文件&#xff08;/etc/my.cnf&#xff09;配置: #开启MySQL慢日志查询开关 slow_query_log1 #设置慢日志的时间为2秒&#xff0c;SQL语句执…

ctfshow pwn40

目录 1. 分析程序 2. 漏洞编写 3. 漏洞验证 1. 分析程序 首先检查程序相关保护&#xff0c;发现程序为32位且只开启了一个NX保护 checksec pwn 使用IDA进行逆向分析代码&#xff0c;查看漏洞触发点&#xff1a; 在main函数中&#xff0c;有一个ctfshow函数&#xff0c;这里…

SQL173 店铺901国庆期间的7日动销率和滞销率

SQL173 店铺901国庆期间的7日动销率和滞销率 SQL题解&#xff1a;店铺动销率与滞销率计算 关键&#xff1a;只要当天任一店铺有任何商品的销量就输出该天的结果&#xff0c;即使店铺901当天的动销率为0。 潜台词&#xff1a;​输出逻辑与店铺901的销售情况无关&#xff0c;只取…

PytorchLightning最佳实践基础篇

PyTorch Lightning&#xff08;简称 PL&#xff09;是一个建立在 PyTorch 之上的高层框架&#xff0c;核心目标是剥离工程代码与研究逻辑&#xff0c;让研究者专注于模型设计和实验思路&#xff0c;而非训练循环、分布式配置、日志管理等重复性工程工作。本文从基础到进阶&…

Apache Flink 实时流处理性能优化实践指南

Apache Flink 实时流处理性能优化实践指南 随着大数据和实时计算需求不断增长&#xff0c;Apache Flink 已经成为主流的流处理引擎。然而&#xff0c;在生产环境中&#xff0c;高并发、大吞吐量和低延迟的业务场景对 Flink 作业的性能提出了更高要求。本文将从原理层面深入解析…

ubuntu上将TempMonitor加入开机自动运行的方法

1.新建一个TempMonitor.sh文件&#xff0c;内容如下&#xff1a;#!/bin/bashcd /fjrobot/ ./TempMonitor &2.执行以下命令chmod x TempMonitor chmod x TempMonitor.sh rm -rf /etc/rc2.d/S56TempMonitor rm -rf /etc/init.d/TempMonitor cp /fjrobot/TempMonitor.sh /etc/…

速卖通自养号测评技术解析:IP、浏览器与风控规避的实战方案

一、速卖通的“春天”来了&#xff0c;卖家如何抓住机会&#xff1f;2025年的夏天&#xff0c;速卖通的风头正劲。从沙特市场跃升为第二大电商平台&#xff0c;到8月大促返佣力度升级&#xff0c;平台对优质商家的扶持政策越来越清晰。但与此同时&#xff0c;竞争也愈发激烈——…

adb: CreateProcessW failed: 系统找不到指定的文件

具体错误 adb devices * daemon not running; starting now at tcp:5037 adb: CreateProcessW failed: 系统找不到指定的文件。 (2) * failed to start daemon adb.exe: failed to check server version: cannot connect to daemon 下载最新的platform-tools-windows 下载最新…

Centos安装HAProxy搭建Mysql高可用集群负载均衡

接上文MYSQL高可用集群搭建–docker https://blog.csdn.net/weixin_43914685/article/details/149647589?spm1001.2014.3001.5501 连接到你搭建的 Percona XtraDB Cluster (PXC) 数据库集群&#xff0c;实现高可用性和负载均衡&#xff0c;建议使用一个中间件来管理这些连接。…

Sql server开挂的OPENJSON

以前一直用sql server2008&#xff0c;自从升级成sql server2019后&#xff0c;用OPENJSON的感觉像开挂&#xff0c;想想以前表作为参数传输时的痛苦&#xff0c;不堪回首。一》不堪回首 为了执行效率&#xff0c;很多时候希望将表作为参数传给数据库的存储过程。存储过程支持自…

【数据结构】队列和栈练习

1.用队列实现栈 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; typedef int QDatatype; typedef struct QueueNode {struct QueueNode *next;QDatatype data; }QNode;typedef struct Queue {QNode* head;QNode* tail;QDatatype size; }Que;typedef struct {Que…

LabVIEW二维码实时识别

​LabVIEW通过机器视觉技术&#xff0c;集成适配硬件构建二维码实时识别系统。通过图像采集、预处理、定位及识别全流程自动化&#xff0c;解决复杂环境下二维码识别效率低、准确率不足问题&#xff0c;满足工业产线追溯、物流分拣等实时识别需求。应用场景适用于工业产线追溯&…

微服务-springcloud-springboot-Skywalking详解(下载安装)

一、SkyWalking核心介绍 1. 什么是SkyWalking&#xff1f; Apache SkyWalking是一款国人主导开发的开源APM&#xff08;应用性能管理&#xff09;系统&#xff0c;2015年由吴晟创建&#xff0c;2017年进入Apache孵化器&#xff0c;2019年毕业成为Apache顶级项目。它通过分布式…

Elasticsearch 字段值过长导致索引报错问题排查与解决经验总结

在最近使用 Elasticsearch 的过程中&#xff0c;我遇到了一个 字段值过长导致索引失败 的问题。经过排查和多次尝试&#xff0c;最终通过设置字段 "index": false 方式解决。本文将从问题现象、排查过程、问题分析、解决方案和建议等方面&#xff0c;详细记录这次踩坑…

使用idea 将一个git分支的部分记录合并到git另一个分支

场景&#xff1a; 有多个版本分支&#xff0c;需要将其中一个分支的某一两次提交合并到指定分支上 eg&#xff1a; 将v1.0.0分支中指定提交记录 合并到 v1.0.1分支中 操作&#xff1a; 步骤一 idea切换项目分支到v1.0.1(需要合并到哪个分支就先站到哪个分支上) 步骤二 在ide…

基于深度学习的图像分类:使用ShuffleNet实现高效分类

前言 图像分类是计算机视觉领域中的一个基础任务&#xff0c;其目标是将输入的图像分配到预定义的类别中。近年来&#xff0c;深度学习技术&#xff0c;尤其是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;在图像分类任务中取得了显著的进展。ShuffleNet是一种轻量级的…

OpenGL里相机的运动控制

相机的核心构造一个是glm::lookAt函数&#xff0c;一个是glm::perspective函数&#xff0c;本文相机的一切运动都在于如何构建相应的参数传入上述两个函数里。glm::mat4 glm::lookAt(glm::vec3 const &eye,//相机所在位置glm::vec3 const &center,//要凝视的点glm::vec…