一文搞懂Android和嵌入式Linux开发差异点

发布时间:2023年12月18日

前言

因业务需要,过去一年从熟悉的Android开发开始涉及嵌入式Linux开发,编程语言也从Java/Kotlin变成难上手的C++,这里面其实有很多差异点,特此整理本文来详细对比这两者开发的异同,便于对嵌入式Linux开发感兴趣的同学一些参考。

适用人群

  • 有一定Android开发经验
  • 想了解嵌入Linux开发的同学

思维导图

架构对比

image.png

注:左边是Android的平台架构,右边是目前我们Linux的平台架构。

由下往上看:

  • 硬件层:硬件层是操作系统与硬件设备之间的桥梁,它使得操作系统和应用程序能够与各种硬件设备进行通信,从而实现设备的控制和管理。设备类型Android对应的比如智能手机、平板、物联网设备等,Linux对应的比如嵌入式设备、物联网设备等。
  • Linux内核:Linux内核是Linux操作系统的核心组件,它负责管理系统的硬件资源、提供程序运行所需的环境以及协调程序之间的相互作用。比如Linux会负责进程管理、内存管理、文件系统、设备驱动、网络协议栈、系统调用和安全和权限管理等。
  • 系统层:这一层包含了一系列用于实现基本的系统功能和服务的库。比如通过libc或glibc来访问操作系统提供的服务。
  • 应用框架层:这一层就是我们常说的Framework,在Android中提供的是用于开发Android应用程序的API和组件,比如Activity、Service、Broadcast Receiver等。在Linux中也有相应的组件和API,一般情况下是通过DBus这种跨进程通信来调用服务,比如日志服务,网络服务等。
  • 应用层:这一层就是最上层我们能看见的应用层,我们在手机能看到的Android App和在嵌入设备看到的Linux应用程序。我们通常使用Java来开发Android应用程序,使用C/C++来开发Linux应用程序。

基础差异对比

项目Android开发嵌入式Linux开发
基础平台基于Linux内核基于Linux内核
开发语言Java/Kotlin(应用层),C/C++(底层库和JNI接口)C/C++,其他语言(如Python)
开发环境Android Studio,Eclipse等Visual Studio Code,Eclipse,Code::Blocks等,或自定义开发环境
用户界面Android UI框架(如XML布局、Activity等)需自选或开发图形界面库(如LVGL、Qt、GTK+等)
系统组件Activity、Service、Broadcast Receiver等无统一系统组件,根据项目需求自行设计和实现
资源管理严格的资源管理规定(如内存、电源等)无统一资源管理规定,需要根据需求进行优化
应用分发Google Play或其他应用市场通过设备制造商或系统集成商进行部署和升级
设备驱动开发Android HAL层设备驱动开发基于Linux内核的设备驱动开发
系统定制和移植Android系统定制和移植嵌入式Linux系统定制和移植
目标设备主要针对移动设备(如手机、平板等)针对各种嵌入式设备(如路由器、工控设备等)

这个表格展示了Android开发和嵌入式Linux开发的主要异同点。虽然它们在底层都基于Linux内核,但在应用开发、用户界面、系统组件等方面有很大的差异。嵌入式Linux的GUI框架就不像Android那么完善和便捷,比如想要实现嵌入式的用户界面,使用C语言开发的LVGL框架来手写界面代码,UI交互代码会显得冗余
example:

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_BTN

static void btn_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * btn = lv_event_get_target(e);
    if(code == LV_EVENT_CLICKED) {
        static uint8_t cnt = 0;
        cnt++;

        /*Get the first child of the button which is the label and change its text*/
        lv_obj_t * label = lv_obj_get_child(btn, 0);
        lv_label_set_text_fmt(label, "Button: %d", cnt);
    }
}

/**
 * Create a button with a label and react on click event.
 */
void lv_example_get_started_1(void)
{
    lv_obj_t * btn = lv_btn_create(lv_scr_act());     /*Add a button the current screen*/
    lv_obj_set_pos(btn, 10, 10);                            /*Set its position*/
    lv_obj_set_size(btn, 120, 50);                          /*Set its size*/
    lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);           /*Assign a callback to the button*/

    lv_obj_t * label = lv_label_create(btn);          /*Add a label to the button*/
    lv_label_set_text(label, "Button");                     /*Set the labels text*/
    lv_obj_center(label);
}

#endif

UI效果如下:
image.png

跨进程通信对比

在Android和Linux系统中,跨进程通信(IPC)是一种用于在不同进程之间传递数据和消息的机制。以下是Android和Linux中跨进程通信的对比:

维度Android IPCLinux IPC
Binder提供Binder机制进行跨进程通信不支持Binder机制
Unix套接字支持Unix域套接字支持Unix域套接字
消息队列不直接支持SysV消息队列,可通过JNI使用支持SysV消息队列和POSIX消息队列
共享内存支持匿名共享内存(ashmem)和内存文件映射支持SysV共享内存和POSIX共享内存
信号受限的信号支持,不推荐用于IPC支持信号(signal)进行简单的进程间通信
管道和有名管道支持管道(pipe)和有名管道(FIFO)支持管道(pipe)和有名管道(FIFO)
信号量不直接支持SysV信号量,可通过JNI使用支持SysV信号量和POSIX信号量
D-Bus不直接支持D-Bus,可通过第三方库使用支持D-Bus进行桌面环境和系统服务间的通信

其中Binder机制是Android开发非常重要的知识点,原理图如下所示:
image.png

图片引自:https://zhuanlan.zhihu.com/p/35519585

Binder的优势在于提供一种高性能、稳定性和安全性跨进程通信机制。基于C/S架构,职责明确、架构清晰;通信过程中仅需要进行一次内存拷贝,性能仅次于共享内存;然而它为每个APP进程分配UID,可以通过UID鉴别身份。

D-Bus
D-BUS是一种进程间通信(IPC)机制,一般主要用于基于AF_UNIX套接字的本地进程间通信(local IPC)(当然也可以基于TCP/IP)实现跨主机的通信。原理图如下所示:

image.png

图片引自:https://hustcat.github.io/getting-started-with-dbus/

D-Bus协议是一个端到端的通信协议,核心基础概念参考:
image.png

编程语言对比

参数JavaKotlinC++
历史1995年由James Gosling 在 Sun Microsystems 开发2011年由JetBrains开发1979年由Bjarne Stroustrup 在贝尔实验室开发
编程范式面向对象面向对象和函数式编程面向过程和面向对象
平台依赖平台无关平台无关平台相关
编译与解释编译解释编译解释仅编译
内存管理系统控制系统控制手动控制
可移植性可移植可移植不可移植
指针有限支持不支持强烈支持
参数传递按值传递按值传递按值传递和按引用传递
重载仅方法重载运算符和方法重载运算符和方法重载
线程支持内置线程支持内置线程支持依赖第三方线程库
文档注释支持支持不支持
兼容性不兼容其他语言兼容Java兼容C语言
goto语句不支持不支持支持
多重继承单继承单继承单继承和多继承
结构体与共用体不支持支持数据类支持
虚拟关键字所有非静态方法默认virtual不支持virtual关键字支持virtual关键字
硬件离硬件较远离硬件较远接近硬件
数据与功能需在类中,可有包作用域需在类中,可有包作用域提供全局作用域和命名空间作用域
运行时错误检测系统处理系统处理程序员处理
根层次结构支持单根层次结构支持单根层次结构无根层次结构
输入输出System.in 和 System.out.printlnprintln和readLine()Cin和Cout

C++、Java和Kotlin之间的最大区别在于它们的编程范式、内存管理和平台依赖性。

  1. 编程范式:C++支持面向过程和面向对象编程,而Java和Kotlin主要支持面向对象编程。Kotlin还支持函数式编程。
  2. 内存管理:C++需要程序员手动管理内存分配和释放,而Java和Kotlin使用自动内存管理(垃圾回收机制),这使得Java和Kotlin更易于使用,但可能在某些情况下牺牲了性能。
  3. 平台依赖性:C++是平台相关的,需要针对不同平台进行编译。Java和Kotlin则是平台无关的,可以一次编写并在任何支持Java虚拟机(JVM)的平台上运行。Kotlin还可以编译为JavaScript和本地代码,从而实现更广泛的平台兼容性。

这些区别使得C++更适合底层系统开发、性能关键应用和嵌入式系统,而Java和Kotlin更适合跨平台应用、Web应用和移动应用开发。

开发工具、编译工具对比

项目Android开发嵌入式Linux开发
开发工具Android Studio, Eclipse等Visual Studio Code,Eclipse, Code::Blocks等, 或自定义开发环境
编译工具Gradle (应用层), Android NDK (底层库和JNI接口)Make, CMake, Autotools等
编译器Java编译器 (应用层), GCC (底层库和JNI接口)GCC, Clang等
调试器Android Debug Bridge (ADB), Logcat, DDMS等GDB, KGDB等
版本控制Git, SVN, Mercurial等Git, SVN, Mercurial等
性能分析工具Android Profiler, Traceview, Systrace等Perf, Valgrind, OProfile等
静态代码分析Lint, SonarQube等Lint, cppcheck, Coverity等
模拟器/仿真器Android模拟器, Genymotion等QEMU, VirtualBox等
持续集成/部署Jenkins, CircleCI, GitLab CI等Jenkins, CircleCI, GitLab CI等

Android开发和嵌入式Linux开发使用的开发工具和编译工具有一些核心差异,以下是一些主要差异点:
开发工具:
Android开发:

  • Android Studio:这是Google为Android开发者提供的官方集成开发环境(IDE),内置了代码编辑器、调试器、模拟器等工具,支持Java和Kotlin语言进行Android应用开发。
  • ADB(Android Debug Bridge):这是一个命令行工具,用于在开发机和Android设备之间进行通信,支持安装应用、查看系统日志、调试应用等功能。

嵌入式Linux开发:

  • Eclipse、Visual Studio Code等通用IDE:这些IDE支持C/C++和其他语言,可以用于嵌入式Linux应用开发。
  • GDB(GNU Debugger):这是一个强大的源代码级调试器,用于调试嵌入式Linux应用程序。

编译工具:
Android开发:

  • Gradle:这是Android的官方构建工具,用于编译和打包Android应用。
  • Android NDK(Native Development Kit):这是一个工具集,用于编译和链接使用C/C++编写的Android应用的本地部分。

嵌入式Linux开发:

  • GCC(GNU Compiler Collection):这是一个开源的编译器集合,用于编译C/C++和其他语言的代码。
  • Make:这是一个构建工具,用于自动化编译和链接过程。
  • CMake:这是一个跨平台的构建系统,用于生成Makefile或其他构建脚本。

包管理和依赖管理对比

项目Android开发嵌入式Linux开发
包管理系统APK (Android Package)dpkg, RPM, ipkg等
包管理工具ADB (Android Debug Bridge)apt-get, yum, opkg等
依赖管理Gradle, Maven等Conan,Makefile, autoconf等
应用分发国内应用商店(小米、华为、OPPO、Vivo等)、Google Play, APKPure等通过设备制造商或系统集成商进行部署和升级
应用更新自建应用升级,OTA升级更新,Google Play自动更新OTA升级更新,也可以手动更新或通过脚本自动更新

在Android和嵌入式Linux开发中,包管理和依赖管理是两个相关的概念,它们共同处理应用程序或系统所需的库、组件和资源。以下是它们在包管理和依赖管理方面的主要区别:

Android包管理和依赖管理:

  1. APK(Android Package Kit):这是Android应用程序的安装包格式,包含了应用程序的所有代码、资源、证书以及清单文件等。
  2. 应用商店:Android应用程序通常通过应用商店(如Google Play、华为应用市场等)进行分发和更新。应用商店负责应用程序的审核、签名、安装、更新等功能。
  3. Gradle:Android Studio使用Gradle作为构建系统,它负责处理应用程序的依赖关系。开发者可以在项目的build.gradle文件中声明所需的第三方库,Gradle会自动从远程仓库(如Maven Central、JCenter等)下载并集成这些库。
  4. Android SDK/NDK:Android SDK提供了一套用于开发Android应用程序的API和组件,而Android NDK提供了一套用于处理本地C/C++代码依赖关系的工具。这些组件已经包含在Android系统中,无需额外处理依赖关系。

嵌入式Linux包管理和依赖管理:

  1. 包格式:嵌入式Linux系统的包格式取决于具体的发行版,如Debian/Ubuntu使用deb包,Red Hat/CentOS使用RPM包,OpenWrt使用opkg包等。
  2. 软件仓库:嵌入式Linux应用程序通常通过软件仓库进行分发和更新。软件仓库是一个包含了预编译软件包的服务器,用户可以通过包管理器(如apt、yum、opkg等)从软件仓库安装和更新软件包。
  3. 包管理器:嵌入式Linux发行版通常提供了一个包管理器(如apt、yum、opkg等),用于自动处理系统和应用程序的依赖关系。开发者可以通过包管理器从软件仓库安装所需的库和组件。
  4. 构建系统:嵌入式Linux开发中,Makefile、autoconf和CMake等构建工具可以用于处理项目的依赖关系。开发者需要在构建脚本中手动声明所需的库和组件。

可运行文件对比

Android APK(Android Package)和Linux的可执行文件是两种不同的应用程序格式,它们分别用于Android和Linux系统。以下是Android APK和Linux可执行文件的对比:

维度Android APKLinux可执行文件
文件格式APK(Android Package)ELF(可执行和可链接格式)
用途Android应用程序的安装包Linux系统上的可执行程序
打包内容应用程序代码、资源、清单文件等可执行代码、数据、符号表等
代码类型Java/Kotlin字节码、C/C++库(可选)通常为编译后的机器代码
运行环境Android运行时(ART)或Dalvik虚拟机直接在Linux操作系统上运行
安装过程通过应用商店或ADB安装到Android设备上通过包管理器、编译安装或手动复制到系统目录
更新机制通过应用商店自动更新或手动更新通过包管理器更新或手动替换可执行文件
安全和权限Android权限模型、应用签名Linux用户/组权限、文件权限等

APK文件一览:
image.png

Android Studio 分析apk:
image.png

Linux中ELF可执行文件一览:
image.png

性能分析工具对比

项目Android开发嵌入式Linux开发
CPU性能分析Traceview, Systrace, Simpleperf等Perf, OProfile, GProf等
内存性能分析Android Profiler, LeakCanary等Valgrind, Massif等
磁盘I/O分析Android Profiler, iostat等iostat, blktrace等
网络性能分析Android Profiler, tcpdump等tcpdump, Wireshark, iperf等
电源性能分析Battery Historian, Systrace等PowerTOP, Intel Energy Profiler等
GPU性能分析GPU Debugging, Systrace等GPU PerfStudio, NVIDIA Nsight等
应用性能分析Android Profiler, Firebase Performance等自定义性能分析工具或第三方库
系统性能分析Systrace, Android Profiler等SystemTap, LTTng, Ftrace等
实时性能分析Systrace, Android Profiler等PREEMPT_RT补丁, RT-Tester等

Android我们关注的性能指标在Linux上其实也大同小异,只是在不同的体系下分析手段和工具不一样。相比于Linux分析Android应用的性能要便捷得多,Android Studio内置了强大的性能分析工具—Android Profiler,可以分析CPU、Memory、Network、Energy和Timeline。

写在最后

本文从架构、主要差异、编程语言、IDE/编译工具、包管理、可运行文件和性能分析工具进行了详细对比,如果是有Android开发经验的要迁移到嵌入式Linux需要学习的内容确实还不少,但研发思路是大同小异的,大致就是通过开发框架和编程语言组织代码,通过跨进程通信来实现服务之间的调用,通过编译工具编译成能在系统运行环境的可执行文件,然后你需要关注如何进行应用更新,需要针对跑起来的应用进行性能分析等等。当然实际的研发工作会更加复杂,要实现一个可商用的产品需要结合业务做更多的能力拓展,比如增加日志上报、崩溃捕获、网络组件、存储组件、异步编程组件等等。

文章来源:https://blog.csdn.net/wwj_748/article/details/135041754
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。