Introduction
Due to business needs, I started to involve in embedded Linux development from the familiar Android development over the past year. The programming language also changed from Java/Kotlin to the more challenging C++. There are actually many differences, and I have organized this article to compare the similarities and differences between these two development environments for those interested in embedded Linux development.
Target Audience
-
Those with some experience in Android development
-
Students who want to learn about embedded Linux development
Mind Map
Architecture Comparison
Note: The left side shows the Android platform architecture, while the right side shows our current Linux platform architecture.
From bottom to top:
-
Hardware Layer: The hardware layer is the bridge between the operating system and hardware devices, allowing the operating system and applications to communicate with various hardware devices for control and management. For Android, this includes devices like smartphones, tablets, and IoT devices, while for Linux, it includes embedded devices and IoT devices.
-
Linux Kernel: The Linux kernel is the core component of the Linux operating system, responsible for managing the system’s hardware resources, providing the environment needed for program execution, and coordinating interactions between programs. For example, Linux handles process management, memory management, file systems, device drivers, network protocol stacks, system calls, and security and permission management.
-
System Layer: This layer includes a series of libraries used to implement basic system functions and services. For example, accessing services provided by the operating system through libc or glibc.
-
Application Framework Layer: This layer is what we commonly refer to as the Framework, which provides APIs and components for developing Android applications, such as Activity, Service, Broadcast Receiver, etc. In Linux, there are also corresponding components and APIs, generally accessed through inter-process communication like DBus for services such as logging and networking.
-
Application Layer: This is the top layer we can see, including Android Apps on phones and Linux applications on embedded devices. We usually use Java to develop Android applications and C/C++ to develop Linux applications.
Basic Differences Comparison
Item |
Android Development |
Embedded Linux Development |
Base Platform |
Based on Linux Kernel |
Based on Linux Kernel |
Development Language |
Java/Kotlin (Application Layer), C/C++ (Lower-level Libraries and JNI Interfaces) |
C/C++, Other Languages (such as Python) |
Development Environment |
Android Studio, Eclipse, etc. |
Visual Studio Code, Eclipse, Code::Blocks, or Custom Development Environment |
User Interface |
Android UI Framework (such as XML Layouts, Activity, etc.) |
Must choose or develop graphical interface libraries (such as LVGL, Qt, GTK+, etc.) |
System Components |
Activity, Service, Broadcast Receiver, etc. |
No unified system components; designed and implemented based on project needs |
Resource Management |
Strict resource management regulations (e.g., memory, power, etc.) |
No unified resource management regulations; needs optimization based on requirements |
Application Distribution |
Google Play or other app markets |
Deployed and upgraded by device manufacturers or system integrators |
Device Driver Development |
Android HAL Layer Device Driver Development |
Device Driver Development based on Linux Kernel |
System Customization and Porting |
Android System Customization and Porting |
Embedded Linux System Customization and Porting |
Target Devices |
Mainly for mobile devices (such as phones, tablets, etc.) |
For various embedded devices (such as routers, industrial control devices, etc.) |
This table presents the main similarities and differences between Android development and embedded Linux development. Although they are both based on the Linux kernel at the lower level, there are significant differences in application development, user interfaces, system components, etc. The GUI frameworks for embedded Linux are not as complete and convenient as Android’s. For example, to implement an embedded user interface, one might have to write the interface code manually using the LVGL framework developed in C, resulting in redundant UI interaction code.
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
The UI effect is as follows:
Inter-Process Communication Comparison
In both Android and Linux systems, inter-process communication (IPC) is a mechanism for transmitting data and messages between different processes. Below is a comparison of IPC in Android and Linux:
Dimension |
Android IPC |
Linux IPC |
Binder |
Provides Binder mechanism for inter-process communication |
Does not support Binder mechanism |
Unix Socket |
Supports Unix domain sockets |
Supports Unix domain sockets |
Message Queue |
Does not directly support SysV message queues, can use JNI |
Supports SysV message queues and POSIX message queues |
Shared Memory |
Supports anonymous shared memory (ashmem) and memory file mapping |
Supports SysV shared memory and POSIX shared memory |
Signals |
Limited signal support, not recommended for IPC |
Supports signals for simple inter-process communication |
Pipes and Named Pipes |
Supports pipes and named pipes (FIFO) |
Supports pipes and named pipes (FIFO) |
Semaphores |
Does not directly support SysV semaphores, can use JNI |
Supports SysV semaphores and POSIX semaphores |
D-Bus |
Does not directly support D-Bus, can use third-party libraries |
Supports D-Bus for communication between desktop environments and system services |
The Binder mechanism is a very important knowledge point in Android development, as shown in the diagram below:
Image source: https://zhuanlan.zhihu.com/p/35519585
The advantage of Binder is that it provides a high-performance, stable, and secure inter-process communication mechanism. Based on the C/S architecture, responsibilities are clear and the architecture is straightforward; during communication, only one memory copy is needed, making its performance second only to shared memory. However, it allocates a UID for each app process, which can be used for identity verification through UID.
D-Bus
D-BUS is an inter-process communication (IPC) mechanism primarily used for local inter-process communication based on AF_UNIX sockets (though it can also be based on TCP/IP) for cross-host communication. The principle diagram is as follows:
Image source: https://hustcat.github.io/getting-started-with-dbus/
The D-Bus protocol is an end-to-end communication protocol, with core foundational concepts as follows:
Programming Language Comparison
Parameter |
Java |
Kotlin |
C++ |
History |
Developed in 1995 by James Gosling at Sun Microsystems |
Developed in 2011 by JetBrains |
Developed in 1979 by Bjarne Stroustrup at Bell Labs |
Programming Paradigm |
Object-oriented |
Object-oriented and functional programming |
Procedural and object-oriented |
Platform Dependency |
Platform-independent |
Platform-independent |
Platform-dependent |
Compilation and Interpretation |
Compiled and interpreted |
Compiled and interpreted |
Compiled only |
Memory Management |
System-controlled |
System-controlled |
Manual control |
Portability |
Portable |
Portable |
Not portable |
Pointers |
Limited support |
No support |
Strong support |
Parameter Passing |
Pass by value |
Pass by value |
Pass by value and pass by reference |
Overloading |
Only method overloading |
Operator and method overloading |
Operator and method overloading |
Thread Support |
Built-in thread support |
Built-in thread support |
Depends on third-party thread libraries |
Document Comments |
Supported |
Supported |
Not supported |
Compatibility |
Not compatible with other languages |
Compatible with Java |
Compatible with C |
Goto Statement |
Not supported |
Not supported |
Supported |
Multiple Inheritance |
Single inheritance |
Single inheritance |
Single and multiple inheritance |
Structures and Unions |
Not supported |
Supports data classes |
Supported |
Virtual Keyword |
All non-static methods are virtual by default |
Does not support virtual keyword |
Supports virtual keyword |
Hardware |
Far from hardware |
Far from hardware |
Close to hardware |
Data and Functions |
Must be in classes, can have package scope |
Must be in classes, can have package scope |
Provides global and namespace scope |
Runtime Error Detection |
Handled by the system |
Handled by the system |
Handled by the programmer |
Root Hierarchy |
Supports single root hierarchy |
Supports single root hierarchy |
No root hierarchy |
Input/Output |
System.in and System.out.println |
println and readLine() |
Cin and Cout |
The biggest differences between C++, Java, and Kotlin lie in their programming paradigms, memory management, and platform dependencies.
-
Programming Paradigm: C++ supports procedural and object-oriented programming, while Java and Kotlin mainly support object-oriented programming. Kotlin also supports functional programming.
-
Memory Management: C++ requires programmers to manually manage memory allocation and release, while Java and Kotlin use automatic memory management (garbage collection), making Java and Kotlin easier to use but potentially sacrificing performance in some cases.
-
Platform Dependency: C++ is platform-dependent and needs to be compiled for different platforms. Java and Kotlin are platform-independent, allowing code to be written once and run on any platform that supports the Java Virtual Machine (JVM). Kotlin can also be compiled to JavaScript and native code for broader platform compatibility.
These differences make C++ more suitable for low-level system development, performance-critical applications, and embedded systems, while Java and Kotlin are more suitable for cross-platform applications, web applications, and mobile application development.
Development Tools and Compiler Tools Comparison
Item |
Android Development |
Embedded Linux Development |
Development Tools |
Android Studio, Eclipse, etc. |
Visual Studio Code, Eclipse, Code::Blocks, or Custom Development Environment |
Compiler Tools |
Gradle (Application Layer), Android NDK (Lower-level Libraries and JNI Interfaces) |
Make, CMake, Autotools, etc. |
Compilers |
Java Compiler (Application Layer), GCC (Lower-level Libraries and JNI Interfaces) |
GCC, Clang, etc. |
Debuggers |
Android Debug Bridge (ADB), Logcat, DDMS, etc. |
GDB, KGDB, etc. |
Version Control |
Git, SVN, Mercurial, etc. |
Git, SVN, Mercurial, etc. |
Performance Analysis Tools |
Android Profiler, Traceview, Systrace, etc. |
Perf, Valgrind, OProfile, etc. |
Static Code Analysis |
Lint, SonarQube, etc. |
Lint, cppcheck, Coverity, etc. |
Emulators/Simulators |
Android Emulator, Genymotion, etc. |
QEMU, VirtualBox, etc. |
Continuous Integration/Deployment |
Jenkins, CircleCI, GitLab CI, etc. |
Jenkins, CircleCI, GitLab CI, etc. |
There are some core differences in the development tools and compiler tools used in Android and embedded Linux development. Here are some of the main differences:
Development Tools:
Android Development:
-
Android Studio: This is the official integrated development environment (IDE) provided by Google for Android developers, which includes a code editor, debugger, emulator, and other tools, supporting Java and Kotlin for Android application development.
-
ADB (Android Debug Bridge): This is a command-line tool that facilitates communication between the development machine and Android devices, supporting application installation, system log viewing, application debugging, and more.
Embedded Linux Development:
-
Eclipse, Visual Studio Code, and other general-purpose IDEs: These IDEs support C/C++ and other languages and can be used for embedded Linux application development.
-
GDB (GNU Debugger): This is a powerful source-level debugger used for debugging embedded Linux applications.
Compiler Tools:
Android Development:
-
Gradle: This is the official build tool for Android, used for compiling and packaging Android applications.
-
Android NDK (Native Development Kit): This is a toolkit for compiling and linking the native parts of Android applications written in C/C++.
Embedded Linux Development:
-
GCC (GNU Compiler Collection): This is an open-source collection of compilers for compiling C/C++ and other languages.
-
Make: This is a build tool for automating the compilation and linking process.
-
CMake: This is a cross-platform build system for generating Makefiles or other build scripts.
Package Management and Dependency Management Comparison
Item |
Android Development |
Embedded Linux Development |
Package Management System |
APK (Android Package) |
dpkg, RPM, ipkg, etc. |
Package Management Tools |
ADB (Android Debug Bridge) |
apt-get, yum, opkg, etc. |
Dependency Management |
Gradle, Maven, etc. |
Conan, Makefile, autoconf, etc. |
Application Distribution |
Domestic app stores (Xiaomi, Huawei, OPPO, Vivo, etc.), Google Play, APKPure, etc. |
Deployed and upgraded by device manufacturers or system integrators |
Application Updates |
Self-built application upgrades, OTA upgrades, Google Play auto-updates |
OTA upgrades, can also be manually updated or automatically updated via scripts |
In Android and embedded Linux development, package management and dependency management are related concepts that handle the libraries, components, and resources required by applications or systems. Here are the main differences in package management and dependency management:
Android Package Management and Dependency Management:
-
APK (Android Package Kit): This is the installation package format for Android applications, containing all application code, resources, certificates, and manifest files.
-
App Store: Android applications are typically distributed and updated through app stores (such as Google Play, Huawei App Market, etc.). The app store is responsible for auditing, signing, installing, and updating applications.
-
Gradle: Android Studio uses Gradle as the build system, which handles the dependencies of applications. Developers can declare the required third-party libraries in the project’s build.gradle file, and Gradle will automatically download and integrate these libraries from remote repositories (such as Maven Central, JCenter, etc.).
-
Android SDK/NDK: The Android SDK provides a set of APIs and components for developing Android applications, while the Android NDK offers tools for handling native C/C++ code dependencies. These components are already included in the Android system, requiring no additional dependency handling.
Embedded Linux Package Management and Dependency Management:
-
Package Format: The package format for embedded Linux systems depends on the specific distribution, such as Debian/Ubuntu using deb packages, Red Hat/CentOS using RPM packages, and OpenWrt using opkg packages.
-
Software Repository: Embedded Linux applications are typically distributed and updated through software repositories. A software repository is a server containing pre-compiled software packages, which users can install and update software packages from using package managers (such as apt, yum, opkg, etc.).
-
Package Managers: Embedded Linux distributions generally provide a package manager (such as apt, yum, opkg, etc.) for automatically handling system and application dependencies. Developers can use the package manager to install the required libraries and components from the software repository.
-
Build Systems: In embedded Linux development, build tools like Makefile, autoconf, and CMake can be used to handle project dependencies. Developers need to manually declare the required libraries and components in the build scripts.
Executable File Comparison
Android APK (Android Package) and Linux executable files are two different application formats used for Android and Linux systems, respectively. Here is a comparison of Android APK and Linux executable files:
Dimension |
Android APK |
Linux Executable File |
File Format |
APK (Android Package) |
ELF (Executable and Linkable Format) |
Purpose |
Installation package for Android applications |
Executable program on Linux systems |
Contents |
Application code, resources, manifest files, etc. |
Executable code, data, symbol tables, etc. |
Code Type |
Java/Kotlin bytecode, C/C++ libraries (optional) |
Usually compiled machine code |
Runtime Environment |
Android Runtime (ART) or Dalvik Virtual Machine |
Runs directly on the Linux operating system |
Installation Process |
Installed on Android devices through app stores or ADB |
Installed through package managers, compiled installation, or manually copied to system directories |
Update Mechanism |
Automatically updated or manually updated through app stores |
Updated through package managers or manually replaced executable files |
Security and Permissions |
Android permission model, application signatures |
Linux user/group permissions, file permissions, etc. |
Overview of APK files:
Analysis of APK in Android Studio:
Overview of ELF executable files in Linux:
Performance Analysis Tools Comparison
Item |
Android Development |
Embedded Linux Development |
CPU Performance Analysis |
Traceview, Systrace, Simpleperf, etc. |
Perf, OProfile, GProf, etc. |
Memory Performance Analysis |
Android Profiler, LeakCanary, etc. |
Valgrind, Massif, etc. |
Disk I/O Analysis |
Android Profiler, iostat, etc. |
iostat, blktrace, etc. |
Network Performance Analysis |
Android Profiler, tcpdump, etc. |
tcpdump, Wireshark, iperf, etc. |
Power Performance Analysis |
Battery Historian, Systrace, etc. |
PowerTOP, Intel Energy Profiler, etc. |
GPU Performance Analysis |
GPU Debugging, Systrace, etc. |
GPU PerfStudio, NVIDIA Nsight, etc. |
Application Performance Analysis |
Android Profiler, Firebase Performance, etc. |
Custom performance analysis tools or third-party libraries |
System Performance Analysis |
Systrace, Android Profiler, etc. |
SystemTap, LTTng, Ftrace, etc. |
Real-time Performance Analysis |
Systrace, Android Profiler, etc. |
PREEMPT_RT patches, RT-Tester, etc. |
The performance metrics we focus on in Android are actually quite similar in Linux, but the analysis methods and tools differ under different systems. Analyzing the performance of Android applications is much more convenient compared to Linux, as Android Studio has a powerful performance analysis tool—Android Profiler—that can analyze CPU, Memory, Network, Energy, and Timeline.
Conclusion
This article provides a detailed comparison from architecture, main differences, programming languages, IDE/compiler tools, package management, executable files, and performance analysis tools. For those with Android development experience looking to transition to embedded Linux, there is indeed a lot to learn, but the development thinking is largely similar. The general approach is to organize code through development frameworks and programming languages, use inter-process communication to implement service calls, compile into executable files that can run in the system environment, and pay attention to how to perform application updates and conduct performance analysis on running applications, among other tasks. Of course, actual development work is much more complex, and to achieve a commercially viable product, more capabilities need to be expanded in conjunction with business requirements, such as adding log reporting, crash capture, network components, storage components, asynchronous programming components, etc.