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

前言

因业务需要,过去一年从熟悉的Android开发 开始涉及嵌入式Linux开发 ,编程语言也从Java/Kotlin变成难上手的C++,这里面其实有很多差异点,特此整理本文来详细对比这两者开发的异同,便于对嵌入式Linux开发感兴趣的同学一些参考。 本文纯抛转引玉,关于嵌入式领域笔者也是在逐步学习中,如有错漏欢迎补充。

适用人群

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

思维导图

架构对比

注:左边是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:

c 复制代码
#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效果如下:

跨进程通信对比

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

维度 Android IPC Linux 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开发非常重要的知识点,原理图如下所示:

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

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

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

图片引自:hustcat.github.io/getting-sta...

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

编程语言对比

参数 Java Kotlin C++
历史 1995年由James Gosling 在 Sun Microsystems 开发 2011年由JetBrains开发 1979年由Bjarne Stroustrup 在贝尔实验室开发
编程范式 面向对象 面向对象和函数式编程 面向过程和面向对象
平台依赖 平台无关 平台无关 平台相关
编译与解释 编译解释 编译解释 仅编译
内存管理 系统控制 系统控制 手动控制
可移植性 可移植 可移植 不可移植
指针 有限支持 不支持 强烈支持
参数传递 按值传递 按值传递 按值传递和按引用传递
重载 仅方法重载 运算符和方法重载 运算符和方法重载
线程支持 内置线程支持 内置线程支持 依赖第三方线程库
文档注释 支持 支持 不支持
兼容性 不兼容其他语言 兼容Java 兼容C语言
goto语句 不支持 不支持 支持
多重继承 单继承 单继承 单继承和多继承
结构体与共用体 不支持 支持数据类 支持
虚拟关键字 所有非静态方法默认virtual 不支持virtual关键字 支持virtual关键字
硬件 离硬件较远 离硬件较远 接近硬件
数据与功能 需在类中,可有包作用域 需在类中,可有包作用域 提供全局作用域和命名空间作用域
运行时错误检测 系统处理 系统处理 程序员处理
根层次结构 支持单根层次结构 支持单根层次结构 无根层次结构
输入输出 System.in 和 System.out.println println和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 APK Linux可执行文件
文件格式 APK(Android Package) ELF(可执行和可链接格式)
用途 Android应用程序的安装包 Linux系统上的可执行程序
打包内容 应用程序代码、资源、清单文件等 可执行代码、数据、符号表等
代码类型 Java/Kotlin字节码、C/C++库(可选) 通常为编译后的机器代码
运行环境 Android运行时(ART)或Dalvik虚拟机 直接在Linux操作系统上运行
安装过程 通过应用商店或ADB安装到Android设备上 通过包管理器、编译安装或手动复制到系统目录
更新机制 通过应用商店自动更新或手动更新 通过包管理器更新或手动替换可执行文件
安全和权限 Android权限模型、应用签名 Linux用户/组权限、文件权限等

APK文件一览:

Android Studio 分析apk:

Linux中ELF可执行文件一览:

性能分析工具对比

项目 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需要学习的内容确实还不少,但研发思路是大同小异的,大致就是通过开发框架和编程语言组织代码,通过跨进程通信来实现服务之间的调用,通过编译工具编译成能在系统运行环境的可执行文件,然后你需要关注如何进行应用更新,需要针对跑起来的应用进行性能分析等等。当然实际的研发工作会更加复杂,要实现一个可商用的产品需要结合业务做更多的能力拓展,比如增加日志上报、崩溃捕获、网络组件、存储组件、异步编程组件等等。

相关推荐
IT利刃出鞘27 分钟前
SecureCRT--使用sftp上传和下载文件
linux·运维·服务器
踩着阴暗的自己向上爬4 小时前
Day05-04-持续集成总结
linux·运维·ci/cd
几度春风里4 小时前
嵌入式Linux系统编程 — 7.2 进程的环境变量
嵌入式·linux系统编程·进程的环境变量
qyhua5 小时前
Linux内网端口转公网端口映射
linux·运维·服务器
Geeker555 小时前
如何在忘记密码的情况下解锁Android手机?
android·网络·macos·华为·智能手机·电脑·手机
wxx21506 小时前
【android】【adb shell】写一个shell脚本,监听进程pid变化
android·adb
j.king6 小时前
开源GTKSystem.Windows.Forms框架让C# winform支持跨平台运行
linux·c#·gtk
stackY、7 小时前
【Linux】:程序地址空间
linux·算法
心死翼未伤8 小时前
【MySQL基础篇】多表查询
android·数据结构·数据库·mysql·算法
喂_balabala8 小时前
Android手机拍照或从本地相册选取图片设置头像-高版本适配
android·开发语言