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

手机APP/开发
230
0
0
2024-03-02
标签   Android

前言

因业务需要,过去一年从熟悉的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:

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

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

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

D-Bus

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

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

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