文章目录
Ubuntu && 安卓内核小技巧
1. Ubuntu 终端命令
- 全局搜索:
grep xxx -niR
- 以 root 权限打开根目录文件夹:
sudo nautilus
- 去除文件锁:
sudo chmod 777 [filename]
- 去除文件夹内所有文件锁:
sudo chmod -R 777 .
- 清空垃圾箱:
sudo rm -rf ~/.local/share/Trash/*
2. 防止编译时因为未使用的变量或函数而引发错误警告
以 pixel 3xl 的内核版本 android-msm-crosshatch-4.9-android12
为例
在 ./private/msm-google/Makefile
中,找到以下代码:
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common -fshort-wchar \
-Werror-implicit-function-declaration \
-Wno-format-security \
-std=gnu89
我们在 -Wno-format-security \
下方加入两条语句:
-Wno-unused-variable \
-Wno-unused-function \
再次编译就不会报错了
3. 查询进程 id 方法
a. shell 方法
-
adb shell dumpsys activity top|grep “ACTIVITY”
查询当前所有活动的进程的 tgid
root@ubuntu:~# adb shell dumpsys activity top|grep "ACTIVITY" ACTIVITY com.ss.android.ugc.aweme/.splash.SplashActivity e05d114 pid=21855 ACTIVITY com.android.launcher3/.uioverrides.QuickstepLauncher 9baf895 pid=2708 ACTIVITY com.taobao.taobao/com.taobao.tao.TBMainActivity f4df805 pid=13263
-
adb shell ps -eo pid,args,psr|grep “包名”
查询指定进程的 pid,包含了当前进程所在的 tgid 中的所有 pid
root@ubuntu:~# adb shell ps -eo pid,args,psr|grep "android.ugc.aweme" 21855 com.ss.android.ugc.aweme 7 22967 com.ss.android.ugc.aweme:push 7
-
adb shell pgrep -f “包名”
查询指定进程的 pid,该方法只输出 pid 不输出其他信息,无法分辨哪一个是主线程的 id
root@ubuntu:~# adb shell pgrep -f android.ugc.aweme 21855 22967
b. 内核查询进程id方法
- task_pid_nr(current):查询当前任务的 pid
- task_tgid_nr(current):查询当前任务的 tgid
4. 终端打印信息:printk()
在内核中加入语句:printk(KERN_EMERG "print what you want in cpu=%d", cpu);
编译过后进入 shell
输入 dmesg -w
可以实时打印你想要的信息
输入 dmesg | grep [关键词]
可以打印已有的你想要的含有关键词
的信息
输入 dmesg -w | grep [关键词]
可以实时打印你想要的含有关键词
的信息
注意:
-
在定义变量代码前边出现printk函数,编译时会出现这个错误:
error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
同时,我们可以利用这个错误,来试探该部分是否被编译。
-
如果频率过高,printk 打印出来的信息可能会错位,如果需要按照时间戳打印最好使用 ftrace 等方式
5. 日志打印信息
a. ftrace(简单介绍)
假如我想要在 /kernel/msm-5.4/kernel/sched/core.c
中加入一个 trace 事件,我可以先看是否有自带的存放 trace point 的头文件,如:#include <trace/events/sched.h>
那么,我可以在 include/trace/events/sched.h
中放入以下代码(可以说是模板):
TRACE_EVENT(data_example,
TP_PROTO(int cpu, struct task_struct *t, bool flag),
TP_ARGS(cpu, t, flag),
TP_STRUCT__entry(
__array( char, comm, TASK_COMM_LEN )
__field( int, cpu )
__field( int, freq )
__field( bool, flag )
),
TP_fast_assign(
memcpy(__entry->comm, t->comm, TASK_COMM_LEN);
__entry->cpu = cpu;
__entry->freq = cpufreq_quick_get(cpu);
__entry->flag = flag;
),
TP_printk("cpu=%d freq=%d switch=%s task_comm=%s",
__entry->cpu, __entry->freq, __entry->flag ? "BEGIN" : "END", __entry->comm)
);
如果编译报错,可能需要加上以下定义代码:
DEFINE_EVENT(data_example, data_example,
TP_PROTO(int cpu, struct task_struct *t, bool flag),
TP_ARGS(cpu, t, flag));
在编译完成刷机结束后,就可以通过以下 shell 命令打开 trace 事件并开始 trace:
echo 0 > /sys/kernel/tracing/tracing_on
// 如果 trace 文件中发现数据不全,可以尝试通过以下 shell 指令解决
echo 96000 > /sys/kernel/tracing/buffer_size_kb
echo 1 > /sys/kernel/tracing/events/sched/data_example/enable
echo 1 > /sys/kernel/tracing/tracing_on
/* 执行操作 */
echo 0 > /sys/kernel/tracing/tracing_on
将 trace 结果文件保存至本地:
// 根据关键词从 trace 结果文件中提取信息
adb shell "cat /sys/kernel/tracing/trace | grep data_example" > data_trace/data_example.txt
// 将整个 trace 结果文件取出
adb pull /sys/kernel/tracing/trace D:\data_trace\trace.txt
6. 定频
进入 adb shell 后将某个簇上的最大频率和最小频率都设定为同一个频率,即可实现定频:
echo {想要的频率} > /sys/devices/system/cpu/cpufreq/policy{想要的簇}/scaling_min_freq
echo {想要的频率} > /sys/devices/system/cpu/cpufreq/policy{想要的簇}/scaling_max_freq
值得注意的是,因为某些策略会导致频率可能定不住。
7. 任务绑核
参考文章:Linux下的绑核命令—taskset
掩码形式绑核
将掩码转换为二进制形式,从最低位到最高位代表物理CPU的#0、#1、……、#n号核。某位的值为0表示不绑该核,1表示绑。比如:0x00000001的二进制为0000…0001,只有第0号核的位置是1,所以表示只绑0号核;0x00000003的二进制为0000…0011,第0和1号核的位置是1,所以表示绑CPU的0号和1号核;再比如0xFFFFFFFF的二进制为1111…1111,所有32个核的位置都为1,所以表示绑CPU的0~31核。
需要注意的是,并非掩码中给出的CPU核就一定会存在,比如0x00000400理论上代表CPU的第10号核,但是该核在真正的计算机上面并不一定是存在的。而且,如果我们试图将物理上并不存的核绑定给某个进程时,会返回错误。掩码形式的绑核命令为:
adb shell taskset -p {16进制的CPU号} {任务pid}
列表形式
列表形式指直接指定要绑的CPU核的列表,列表中可以有一个或多个核。具体语法如下:
adb shell taskset -cp {10进制的CPU号,可以以逗号分隔} {任务pid}
其中cpu-list是数字化的cpu列表,从0开始。多个不连续的cpu可用逗号连接,连续的可用短现连接,比如0,2,5-11等。
比如taskset -cp 0,2,5-11 9865命令表示将进程9865绑定到#0、#2、#5~#11号核上面。
最后要说的是:只要taskset成功返回了,那就表示绑核一定成功了,即该进程已被绑到指定的核上面,而且taskset命令会显示原来的绑核(原来的可能是系统默认分配的核)情况,以及新的绑核情况。