AOSP+WSL+adb搭建安卓开发ebpf环境

news2024/11/26 12:37:33

0.写在前面

首先我们要明白,安卓的AOSP包含了海量的代码,他包含了包括了:

1.不同架构下(音响,手机,电视等等各种基于安卓的设备)的上层应用 + 2.Java API Framework(大部分安卓开发者处理的抽象层)+3.C/C++ 底层Lib 以及 Android Runtime环境 +4. HAL外设抽象层(驱动)+ 5.Linux Kernel(最底层)
77fbd87c864c60eb9196328109a02637.png
所以,我们在要以此为大前提去考虑整个开发环境怎么搭建,为什么要那么搭建,以及如何针对具体情况搭建。

平台架构 | Android 开发者 | Android Developers

另外:安卓只是一个mainline,不同厂商可能会各种diy安卓mainline的代码,所以会导致我们搭建环境和测试中在不同的版本有着不同的处理方法,需要我们折腾折腾找解决方案。

1.下载AOSP代码

下载环境依赖

我的云服务器是ubuntu2204,留了400G空间(实际只需要150G),如果要整体编译,确保你的内存在32G及以上。

如果你的/usr/bin只有python3,没有python,请建立软连接或者alias

sudo ln -s /usr/bin/python3 /usr/bin/python

安装依赖:

sudo apt-get update
sudo apt-get install openjdk-8-jdk
sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

工具:repo

正如谷歌V8一样,大型的项目方往往都维护了自己的构建工具,安卓的AOSP(**Android Open Source Project**),不但在构建中使用了自己的“三层”构建系统,下载源码时甚至都使用**repo**进行跨仓库之间的源码管理。
[repo](https://gerrit.googlesource.com/git-repo/+/refs/heads/master/README.md)

repo其实就是git的封装和针对安卓的客制化,具体我也没太看,应该就是方便不同的库引用别的库的各种东西?大概是方便模块化吧。

下载repo工具

mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo 
chmod a+x ~/bin/rep
如果你不确定能一次性弄完(在结束当前shell的session前),记着把PATH=~/bin:$PATH<span style="background:#ff4d4f">持久化的写到~/.bashrc中</span>(export或者直接加到PATH里),每次打开bash命令行都会先运行bashrc,加载各种环境变量和alias等等。

初始化,下载源码

因为repo是git的封装,所以git需要的,repo也不能少,确保你设置了git config username和email

mkdir ad_13
cd ad_13

//if 可以科学上网
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r45
//初始化仓库

//else
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-13.0.0_r45

如果要下11版本就改成android-11.0.0_r45就行了

-b是选择分支,随着代码的更新版本会不断前进,分支就是为了过去的各种版本开辟的一条新的文件track和update,fix的路线。

最后执行 repo sync。

大概下载150G,可能会持续一晚上,下载完以后还会执行git的索引更新,还需要等一段时间,如果突然断开重新运行就行了,下载的东西以及被cache住了。

下载源代码 | Android 开源项目 | Android Open Source Project

2.构建ebpf文件和依赖

文件目录架构,初始化工具

下载好以后运行

source build/envsetup.sh

来初始化编译需要的工具的环境。

进入repo目录可以看到架构如下

art:Android Runtime,一种App运行模式,区别于传统的Dalvik虚拟机,旨在提高Android系统的流畅性
bionic:基础C库源代码,Android改造的C/C++库
bootable:Android程序启动导引,适合各种bootloader的通用代码,包括一个recovery目录
build:存放系统编译规则及generic等基础开发包配置
cts: Android兼容性测试套件标准
dalvik:Android Dalvik虚拟机相关内容
developers:Android开发者参考文档
development: Android应用开发基础设施相关
device:Android支持的各种设备及相关配置
external:Android中使用的外部开源库
frameworks:应用程序框架,Android系统核心部分,由Java和C++编写
hardware:硬件适配接口
kernel:Linux Kernel,不过Android默认不提供,需要单独下载,只有一个tests目录
libcore:Android Java核心类库
libnativehelper:Android动态库,实现JNI库的基础
packages:应用程序包
pdk:Plug Development Kit 的缩写,本地开发套件
platform_testing:Android平台测试程序
prebuilts:x86和arm架构下预编译的一些资源
sdk:Android的Java层sdk
system:Android底层文件系统库、应用和组件
test:Android Vendor测试框架
toolchain:Android工具链文件

ebpf组件就在/system/bpf中,其中有个bpfloader,**这个可以帮助我们热插拔ebpf文件**。
同时aosp也有自己的ebpf测试文件在/system/bpfprogs中有个time_in_state,如果遇到问题可以看看这个示例程序是怎么写的。

创建

进入/external下,创建我们的mybpf文件夹。

创建我们的两个bpf文件(使用libbpf, libbpf_bcclibbpf_android等进行开发)和Android.bp构建文件。

  • 1.bpf_cli.cpp(在userspace接收ebpf的map信息)
#include <android-base/macros.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <bpf/BpfMap.h>
#include <bpf/BpfUtils.h>
#include <libbpf_android.h>
#include "libbpf.h"

int main() {
    constexpr const char tp_prog_path[] = "/sys/fs/bpf/prog_bpf_test_tracepoint_sched_sched_switch";
    constexpr const char tp_map_path[] = "/sys/fs/bpf/map_bpf_test_cpu_pid_map";
    // Attach tracepoint and wait for 4 seconds
    int mProgFd = bpf_obj_get(tp_prog_path);
    // int mMapFd = bpf_obj_get(tp_map_path);
    bpf_attach_tracepoint(mProgFd, "sched", "sched_switch");
    sleep(1);
    android::bpf::BpfMap<int, int> myMap(tp_map_path);

    while(1) {
        usleep(40000);

        // Read the map to find the last PID that ran on CPU 0
        // android::bpf::BpfMap<int, int> myMap(mMapFd);
        printf("last PID running on CPU %d is %d\n", 0, *myMap.readValue(0));
    }
    exit(0);
}
  • 2.bpf_test.c
#include <linux/bpf.h>
#include <stdbool.h>
#include <stdint.h>
#include <bpf_helpers.h>

DEFINE_BPF_MAP(cpu_pid_map, ARRAY, int, uint32_t, 1024);

struct switch_args {
    unsigned long long ignore;
    char prev_comm[16];
    int prev_pid;
    int prev_prio;
    long long prev_state;
    char next_comm[16];
    int next_pid;
    int next_prio;
};

// SEC("tracepoint/sched/sched_switch")
DEFINE_BPF_PROG("tracepoint/sched/sched_switch", AID_ROOT, AID_NET_ADMIN, tp_sched_switch) (struct switch_args* args) {
// int tp_sched_switch(struct switch_args* args) {
    int key;
    uint32_t val;

    key = bpf_get_smp_processor_id();
    val = args->next_pid;

    bpf_cpu_pid_map_update_elem(&key, &val, BPF_ANY);
    return 0;
}

// char _license[] SEC("license") = "GPL";
LICENSE("Apache 2.0");

3.Android.bp

bpf {
    name: "bpf_test.o",
    srcs: ["bpf_test.c"],
    cflags: [
        "-Wall",
        "-Werror",
    ],
}

cc_binary {
    name: "bpf_cli",

    cflags: [
        "-Wall",
        "-Werror",
        "-Wthread-safety",
    ],
    clang: true,
    shared_libs: [
        "libcutils",
        "libbpf_android",
        "libbase",
        "liblog",
        "libnetdutils",
        "libbpf_bcc",
    ],
    static_libs: [
        "libbpf",
    ],
    srcs: [
        "bpf_cli.cpp",
    ],
}

构建

在最开始的时候我们也说了,大型项目往往有自己的构建系统。比如Linux需要deconfig,Makefile,Kconfig,.config详情可以看我的这篇文章Linux从模块化机制学到Kconfig,Makefile构建配置原理_makefile与kconfig_LiujiaHuan13的博客-CSDN博客

那么首先我们在庞大源码下要有个“指路人”,指引在不同的条件编译中,如何编译类似硬件厂商提供的deconfig,我们需要

lunch aosp_arm64-eng

来选择指定架构。

这里主要是针对整体构建,由于我们只build自己的文件,所以有没有这一步无所谓,以防万一,还是lunch上好。

接着,打开/externel/libbpf的Android.bp,在“visibility”中加上"//external/mybpf",使得libbpf在构件中对我们的Android.bp可见。

1.如果遇到问题就把对应报错的库中的Android.bp中的visibility加上我们的文件夹路径。

2.我在尝试的过程中发现aosp13无法以共享库.so的方式使用libbpf,不然会报错‘missing variant’

最后我们分别在

  • /system/bpf中执行mma(构建当前目录所有内容)
  • repo根目录 执行m bpf_clim bpf_test.o

这一块非常慢,不知道为什么,可能第一次编译,且从根目录,搜索和索引占了很长时间?而且这里很容易报错,具体报错就慢慢折腾吧(偷摸一把辛酸泪)

关于Android.bp

在Android 7 之前,使用的是我们常用的Makefile,后来换成了”Soong“构建系统
Soong 构建系统 | Android 开源项目 | Android Open Source Project,Makefile也就变成了Android.bp,和Linux一样,从最底层到上层每一层都有Android.bp文件。

3. 实机调试

设备:

中兴远航41 安卓13

导出文件

这时候用scp导出

  • out/target/product/generic/system/etc中的bpf_test.o
  • out/target/product/generic/system/bin的bpf_cli,和bpfloader(热加载用)
  • 还有out/target/product/generic/system/lib (依赖库)

具体scp怎么用,google或者csdn吧。。。写不动了

安装工具

这里我使用的是windows平台

其实整个过程都可以在windows上完成,其余的用vscode连远程服务器操作,scp在windows的中端也能用

安装 https://download.mydrivers.online/file/mydriversonline/adb-setup-1.4.3.zip adb工具,如果提示你是否安装驱动一定要yes,不然fastboot程序识别不到devices。

导入ebpf文件

  • 在命令行中进入到你scp导出文件的目录,运行adb remount,如果提示你failed,如果你用的是中兴手机,中兴远航41,确定你打开了OEM,那么这个时候不用去网上找教程
  • 只需要adb reboot bootloader,然后fastboot reboot recovery进入恢复分区,这个时候看你手机上有一个”高级设置“然后点击”挂载系统目录“,返回上层,重启。(fastboot如果报错看看是否fastboot devices能识别到?如果识别不到看看设备管理器是否识别为fastboot设备,还是只是其他设备,如果是其他设备那么应该是驱动问题)
    80f95f19a73947ec14cdac3eab4ca058.jpeg
  • 然后重新adb remount ,然后进入adb shell,接着chmod 777 /system,exit退出来,
  • push文件,如果还没权限,重试remount和chmod 777
adb push bpf_test.o  /system/etc/bpf/
adb push bpf_cli bpfloader /data/local/tmp
adb push ./lib/* /data/local/tmp/
  • 赋予程序运行权限
chmod 777 ./bpf_cli ./bpfloader

热加载ebpf

因为ebpf文件会在启动的时候自动加载,但是我们重新启动,/system分区会被重新加载

(对,没错,所谓的chmod 777 可读写只是暂时的,但是我们生产中会把我们的ebpf文件放在源码中重新build,这样开机就能自动运行了)

运行./bpfloader进行热加载,此时看/sys/fs/bpf/会看到map_bpf_test_cpu_pid_map文件成功被建立。

然后运行./bpf_cli,如果报错缺少运行时库,就export一下环境变量export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/date/local/tmp/lib
此时就可以看到371933c32315b16e4394d204997d9d10.png,这里读取id是0的bug正在解决。

Congratulations!你的开发环境已经成功部署了。走下来这一套,已经迈向了安卓ebpf开发的第一步。也是笔者目前起步的状态。

笔者目前就读于西安邮电大学计算机科学与技术专业,大二,对计算机体系结构和操作系统非常感兴趣,从初中开始靠自驱力和兴趣不断接触相关领域知识。关于我可以看这里about - JiaHuann’s Blog.

Refs

搭建编译环境 | Android 开源项目 | Android Open Source Project
源代码控制工具 | Android 开源项目 | Android Open Source Project
Android 操作系统源代码文档 | Android 开源项目 | Android Open Source Project

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

叉积求二维空间两直线交点以及过两点的直线数学原理

叉积求二维空间两直线交点以及过两点的直线数学原理_wang.chen.xue的博客-CSDN博客

ThreeJS教程:屏幕坐标转标准设备坐标

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 屏幕坐标转标准设备坐标 在讲解下节课鼠标点击选中模型之前&#xff0c;先给大家讲解下坐标系的问题。 获取鼠标事件坐标 先来了解一些&#xff0c;普通的web前端相关知识。 鼠…

aop原理

1. 使用 1.1 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>1.2 定义切面类 定义一个切面类&#xff0c;指定增强的方法&#xff0c;方法前两个注解必须…

Axure教程—滚动加载(中继器 )

本文将教大家如何用AXURE中的中继器制作滚动加载效果 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://awjggr.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87867798?spm1001.2014.3001.5503 二、功能介绍 向下滚动鼠…

联想YOGA Pro14s电脑运行时总是蓝屏怎么办?

联想YOGA Pro14s电脑运行时总是蓝屏怎么办&#xff1f;最近有用户在使用电脑的时候&#xff0c;电脑总是会自动变成蓝屏&#xff0c;导致自己的操作中断。那么遇到这个情况要怎么去进行问题的解决呢&#xff1f;接下来我们来看看以下的详细解决方法分享吧。 准备工作&#xff1…

通过python封装关键词搜索1688商品列表数据API、1688商品列表API接口、1688API接口

1688商品详情接口是一种用于访问阿里巴巴旗下的批发市场平台上的商品列表信息的API接口。通过该接口&#xff0c;可以获取商品的详细信息&#xff0c;包括商品名称、规格、价格、描述、图片等。这些信息对于买家和卖家来说都非常重要&#xff0c;可以帮助他们更好地了解商品&am…

MyBatisPlus3-条件查询和映射问题(字段、表名)

1. 条件查询三种方式 条件查询多用第三种&#xff1b; 链式写表示且的关系&#xff0c;中间加上or()表示或的关系&#xff1b; 给出相应示例代码&#xff1a; Test public void testGetList(){//方式一&#xff1a;按条件查询/*QueryWrapper<User> userQueryWrapper new…

基于WebGL的智慧化工三维可视化管理系统

前言 作为全球化学品第一生产大国&#xff0c;我国危险化学品规模总量大、涉及品种多、应用范围广、管理链条长、安全风险高&#xff0c;历来是防范化解重大安全风险的重点领域。 危险化学品领域频繁发生的典型事故&#xff0c;暴露出传统安全风险管控手段问题突出。 建设背景…

【裸机驱动LED】使用汇编代码驱动LED(一)—— 寄存器解析篇

为了后续使用C语言驱动LED&#xff0c;事先学习汇编代码驱动LED&#xff0c;有如下好处&#xff1a; 熟悉一些基本的汇编语法了解驱动LED的基本流程了解驱动LED需要用到哪些寄存器作为一个初学者&#xff0c;可以锻炼自己阅读开发文档的能力 本文的主要目的是了解驱动LED的基…

【手撕Spring源码】SpringBoot启动过程中发生了什么?

文章目录 SpringBoot启动过程启动详解启动演示启动过程总结 SpringBoot启动过程 启动详解 SpringBoot的启动分为两个部分&#xff1a; 构造SpringApplication执行run方法 接下来我们先来看看构造方法里面都做了什么事情。 第一步&#xff1a;记录 BeanDefinition 源 大家知…

Jenkins配置邮件通知+钉钉通知,任务构建状态随时掌握

1.前言 Hello&#xff0c;各位小伙伴&#xff0c;大家好&#xff01;&#xff01;&#xff01; 在前面的文章中&#xff0c;我们实现了用Maven项目任务和Pipeline流水线任务来完成对项目的自动化部署。 DockerJenkinsGitee自动化部署maven项目 DockerJenkinsGiteePipeline部…

0001欧几里得算法

首先我们先了解欧几里得这个人。俗话说&#xff1a;不了解一个人&#xff0c;很难走进他的思想。欧几里得是约公元前330年~公元前275年的古希腊数学家&#xff0c;被称为“几何之父”。《几何原本》就是他的著作。而欧几里得算法是《几何原本》中的一个用于求两个数的最大公约数…

以AI为灯,照亮医疗放射防护监管盲区

相信绝大部分人都有在医院拍X光片的经历&#xff0c;它能够让医生更方便快速地找出潜在问题&#xff0c;判断病人健康状况&#xff0c;是医疗诊断过程中的常见检查方式。但同时X射线也是一把双刃剑&#xff0c;它的照射量可在体内累积&#xff0c;对人体血液白细胞有杀伤力&…

mysql加索引,数据库卡死

公司的一个内部项目&#xff0c;由于突然导入了几十万的数据&#xff0c;数据量翻了一倍&#xff0c;导致了某个页面打开很慢。通过sql日志看到主要是由于慢查询引起的&#xff0c;通过explain这个sql&#xff0c;发现主要是由于这个SQL没有命中索引&#xff0c;进行了全表扫描…

原型模式的用法

文章目录 一、原型模式的用法1.1 介绍1.2 结构1.3 原型模式类图1.4 实现1.4.1 克隆的分类1.4.2 代码 1.5 "三好学生"奖状案例1.5.1 "三好学生"奖状类图1.5.2 代码 1.6 深、浅克隆的区分1.6.1 浅克隆1.6.2 深克隆 一、原型模式的用法 1.1 介绍 用一个已经…

STL(结)

STL&#xff08;结&#xff09; map存储结构基本操作equal_range遍历方式 插入 multimapsetunordered_mapmap和无序map的异同mapunordered_map map 存储结构 map容器的底层存储是一个红黑树&#xff0c;遍历方式都是按照中序遍历的方式进行的。 int main() {std::map<int…

数组降维

写一个函数&#xff0c;打印数组内的内容&#xff0c;代码为&#xff1a; #include<stdio.h>void show_arr(int arr[], int num) {int i 0;for (i 0; i < num; i){printf("%d ", arr[i]);}printf("\n"); } int main() {int arr[] { 1,2,3,4,5…

Servlet Cookie基本概念和使用方法

目录 Cookie 介绍 Cookie 主要有两种类型&#xff1a;会话 Cookie 和持久 Cookie。 Cookie使用步骤 使用Servlet和Cookie实现客户端存储的登录功能示例&#xff1a; LoginServlet类 index.jsp 删除Cookie 浏览器中查看Cookie的方法 Cookie 介绍 Cookie 是一种在网站和…

win10下载安装mysql8.0版本

打开官网下载&#xff1a;https://dev.mysql.com/downloads/mysql/ 下载完成后解压&#xff0c;这里我是直接放在C盘 然后打开mysql目录文件夹新建my.ini文件,my.ini文件内容如下&#xff0c;需要修改两个地方&#xff0c;其中datadir你自己的mysql的安装目录&#xff0c;data…

如何在线压缩png图片?png压缩图片大小的方法介绍

压缩PNG图片大小的优点 随着数字化时代的发展&#xff0c;PNG格式已成为一种常见的图片格式。然而&#xff0c;由于高分辨率、高色深等原因&#xff0c;PNG图片通常具有较大的文件体积&#xff0c;导致在传输、存储和网页加载等方面会产生不必要的负担。因此&#xff0c;对于需…