Linux上应用竟然可以轻松的移植到RTOS上

简介: Linux上应用竟然可以轻松的移植到RTOS上

今天讲的主题是 “如何轻松地移植Linux应用到AliOS Things上

 

1、前言

近些年,大量的智能设备已经进入人们的生活, 如智能音箱,各种支付设备,大街小巷上各种大小的广告机等。这些设备中大多还是采用Linux,带屏的设备则大多采用Android,导致他们必须采用较高成本的硬件。

AliOS Things是阿里云IoT研发的应用于物联网智能设备的嵌入式实时操作系统,是HaaS100搭载的操作系统。目前AliOS Things + 小程序框架已经可以替代Linux甚至Android,大大降低设备的成本。可是Linux(包括Android)上的成熟稳定的框架,尤其是音视频处理的框架,图形渲染等,如果可以拿来使用,再加以适配优化,不需要重复造轮子,岂不美哉。

 

那如何把Unix/Linux这些优秀的框架轻松地移植到AliOS Things上呢?支持POSIX就是实现这个目标的一把利器。

 

2、POSIX是什么

POSIX(Portable Operating System Interface)是IEEE组织为了维护应用在不同操作系统之间的兼容性而制定的标准。 主要包括API,Shell和Utility等一整套应用运行环境。广泛应用于UNIX/LINUX操作系统,和一些嵌入式操作系统中(如Zephyr, VxWorks, QNX, Fuchsia,FreeRTOS,RT-Thread,AliOS Things)。

 

POSIX标准也被称为IEEE 1003,ISO/IEC 9945,目前标准的开发者是Austin Group,它是IEEE, Open Group, ISO/IEC的联合组织,目前POSIX标准的最新版本是POSIX.1-2017。 刚开始时POSIX标准(IEEE 1003)又分为不同的子集,其中还处于有效状态的有IEEE 1003.13。 IEEE 1003.13是针对嵌入式领域制定的标准,根据范围的大小又分为4个不同的Profile,PSE51, PSE52, PSE53和PSE54,其关系如下图。

 

3、为什么需要POSIX

AliOS Things作为一个物联网领域的嵌入式实时操作系统为什么要支持POSIX标准呢?除了解决前言引入的问题外,还有没有其他的目的呢?本章节将进行一个全面的阐述。

 

3.1、POSIX解决的核心问题

软件生态

软件生态是一个OS的生存核心,但建设一个OS的软件生态又不能急于求成, 需要经过多年的积累沉淀。 显然AliOS Things的生态还不成熟,而Linux的生态则经过了几十年的沉淀,变得非常强大。支持POSIX则可以

  • 兼容Unix/Linux软件生态。
  • 兼容支持POSIX标准的嵌入式系统(如FreeRTOS)的软件生态。

 

标准

  • API模型由国际权威组织定义,且被广泛使用验证过,成熟稳定。

 

易用

  • API被广大开发者所熟悉,降低开发者学习成本。
  • 每个API都有标准化的文档详细说明,方便查询使用。
  • 为AliOS Things内部组件提供标准接口,方便使用和支持多平台如移植到Linux。

 

3.2、竞品分析

其实不只有我们这么想,让我们一起看看业界的嵌入式实时操作系统是否支持POSIX标准。

 

VxWorks

作为比较老牌的嵌入式实时操作系统,VxWorks被广泛应用于多个领域,如航空航天,工业控制等对实时性要求很高的领域, 它也是非常重视对POSIX标准的支持,其全部支持了PSE52标准 + BSD Socket。并通过官方的PSE52认证。

 

QNX

作为被广泛应用于汽车领域的嵌入式实时操作系统,同时也是比较成功的商用微内核操作系统,QNX也是比较重视对POSIX标准的支持,其全部支持了PSE52标准 + BSD Socket。

 

Fuchsia

作为Google全新设计研发的微内核操作系统, Fuchsia也是支持POSIX标准的。

FreeRTOS

FreeRTOS虽然主要应用于资源比较受限的MCU设备, 其也实现部分PSE52范围内的API。

 

RT-Thread

RT-Thread主要应用于物联网领域的智能设备, 其也比较重视对POSIX标准的支持,实现PSE52范围内的大部分API。

 

AliOS Things支持POSIX的长远目标是实现POSIX.1的最新版本,如目前是POSIX.1-2017,它共有1191个API,数量是非常大的,但是有很多并不是经常使用的API,因此短期目标是实现PSE52 + Networking标准的API + 项目中需要的API。

 

4、POSIX的设计与实现

POSIX作为内核与应用的接口层, 涉及到内核的多个方面。 下面仅以POSIX线程和POSIX条件变量为例介绍其设计与实现,POSIX组件的代码位于core/osal/posix/, 头文件位于include/posix/。

 

4.1、POSIX线程

关键数据结构

typedef struct pthread_tcb {

    aos_task_t task;    /* The rhino task handle. */

    unsigned int magic; /* The pthread tcb memory magic number. */

    void *(*thread_entry)(void *para); /* The start routine of the thread. */

    void *thread_para;   /* The parameter of start routine. */

    aos_sem_t join_sem;  /* The semaphore for pthread_join. */

    pthread_cleanup_t *cleanup; /* The registered cleanup function for the thread.*/

    void *environ;

    void **tls;

    void  *return_value; /* The thread's return value. */

    pthread_attr_t  attr; /* The thread's attribute. */

    char thread_name[PTHREAD_NAME_MAX_LEN + 1];  /* The thread's name. */

} pthread_tcb_t;

_pthread_tcb_t是POSIX线程内部的核心数据结构,保存着POSIX线程的关键数据,与内核task的tcb结构相对应,且通过tid相互关联。POSIX线程的关键数据类型pthread_t会关联到这个数据结构上。

  • task 内核rhino的任务句柄。
  • magic 是POSIX线程的魔术字,以区别于使用AliOS Things原生的AOS API创建的线程。
  • thread_entry 新创建线程的执行入口函数的指针。
  • thread_para 新创建线程的执行入口函数的参数结构指针。
  • join_sem 实现线程的JOINABLE的信号量,线程退出时自身不释放ptcb资源,由其他线程调用pthread_join获取返回值,并释放资源。
  • cleanup 线程在退出时要执行的清理函数指针的链表。
  • environ 线程运行的环境变量。
  • tls  存放线程私有数据。
  • return_value 存放POSIX线程的返回值的指针。
  • attr 线程属性,为POSIX线程设置属性以更细粒度地控制线程的行为。如线程的栈地址,栈大小,线程的调度策略,调度参数等。
  • thread_name 线程名字

 

POSIX线程的创建与销毁

使用pthread_create创建POSIX线程。

使用pthread_exit销毁一个POSIX线程, 或者从一个线程的入口函数返回,也会走到线程的销毁流程。

下面流程图为保持逻辑清晰,略去了很多实现细节如异常处理等。

 

 

4.2、POSIX条件变量

POSIX条件变量的标准定义:https://pubs.opengroup.org/onlinepubs/9699919799/

关键数据结构

typedef struct pthread_cond {

    uint8_t flag;

    int     waiting;

    int     signals;

    void    *lock;

    void    *wait_sem;

    void    *wait_done;

    pthread_condattr_t attr;

} pthread_cond_t;

pthread_cond_t是实现POSIX条件变量的核心数据结构。

  • flag 一些内部的标记如是否为动态初始化。
  • lock 是保护内部数据的一把mutex锁。
  • waiting 等待这个条件变量的线程数。
  • signals 已发送信号还未收到确认的数目。
  • wait_sem 线程等待的信号量,底层内核的信号量原语。
  • wait_done 用于发送线程与等待线程之间握手确认的信号量, 底层内核的信号量原语。
  • attr 记录pthread条件变量的属性,比如条件变量用到的时钟clock。

 

POSIX条件变量的处理

POSIX 条件变量不仅支持触发单个等待的线程,同时还支持广播(pthread_cond_broadcast),触发多个等待的线程。

 

4.3、实现结果如何

AliOS Things 支持了pthread,semaphore, message queue, timer, fs等多个模块的丰富的API,开发者可以利用这些POSIX API,只需要简单地修改,甚至无需修改,就可以移植Unix/Linux的应用到AliOS Things上。再结合HaaS100的开发板,开发者可以更快速地构建智能设备所需的软件和硬件。

 

4.4、动手试试

下面动手编写一个简单的使用POSIX PTHREAD API的Linux应用,保存为pthread_test.c


 
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <pthread.h>
  4. static volatile int count = 1;
  5. pthread_mutex_t count_lock;
  6. void* increase_count(void *arg)
  7. {
  8.     while ( 1) {
  9.         sleep( 1);
  10.         pthread_mutex_lock(&count_lock);
  11.         count += 10;
  12.         printf( "In new thread: count:%d\n", count);
  13.         pthread_mutex_unlock(&count_lock);
  14.     }
  15. }
  16. int main(int argc, char* argv[])
  17. {
  18.     int ret = 0;
  19.     pthread_t new_thread;
  20.     pthread_mutex_init(&count_lock, NULL);
  21.     ret = pthread_create(&new_thread, NULL, increase_count, NULL);
  22.     if (ret != 0) {
  23.         printf( "Error:%s:%d:ret:%d\n", __FILE__, __LINE__, ret);
  24.         return -1;
  25.     }
  26.     while( 1) {
  27.         sleep( 1);
  28.         pthread_mutex_lock(&count_lock);
  29.         count++;
  30.         printf( "In main thread: count:%d\n", count);
  31.         pthread_mutex_unlock(&count_lock);
  32.     }
  33.    
  34.     return 0;
  35. }

在Linux上编译


 
gcc pthread_test.c -o pthread_test -lpthread

 

运行结果如下:


 
  1. $ ./pthread_test
  2. In main thread: count: 2
  3. In new thread: count: 12
  4. In main thread: count: 13
  5. In new thread: count: 23
  6. In main thread: count: 24
  7. In new thread: count: 34
  8. In main thread: count: 35
  9. In new thread: count: 45
  10. In main thread: count: 46
  11. In new thread: count: 56
  12. In main thread: count: 57
  13. In new thread: count: 67
  14. In main thread: count: 68
  15. In new thread: count: 78
  16. In main thread: count: 79
  17. In new thread: count: 89
  18. In main thread: count: 90
  19. In new thread: count: 100

 

把上面的pthread_test.c 移植到AliOS Things上,改写application/example/helloworld_demo 这个demo应用。 把pthread_test.c 的内容替换application/example/helloworld_demo/appdemo.c的全部内容,并做如下2个简单的修改。


 
  1. $ diff -ru pthread_test.c solutions/helloworld_demo/helloworld.c
  2. --- pthread_test.c 2021-06-17 12:01:56.638675133 +0800
  3. +++ solutions/helloworld_demo/helloworld.c    2021-06-17 12:04:58.479941329 +0800
  4. @@ -17,7 +17,7 @@
  5.  }
  6. -int main(int argc, char* argv[])
  7. +int application_start(int argc, char* argv[])
  8.  {
  9.      int ret = 0;
  10.      pthread_t new_thread;

 

由上可知,AliOS Things的应用入口是application_start, 不是main, 上面的Linux应用,只需要改动一行就可以跑到AliOS Things上。

 

在VSCODE IDE利用alios-studio插件,点击编译按钮,编译hellworld_demo, 详细步骤可以参考 AliOS Things的编译步骤

 

下载烧录并启动,log如下, 与Linux运行的结果一致。

  


 
  1.            Welcome to AliOS Things          
  2.      1592/main_task | sys_init aos_components_init done
  3.      1592/main_task |         mesh has been opened       
  4.      1986/mcu_audio | mcu_audio_main exit
  5. [Jan 01 00: 00: 01.491]<I>ULOG-test sys_init aos_components_init done
  6. In main thread: count: 2
  7. In new thread: count: 12
  8. In main thread: count: 13
  9. In new thread: count: 23
  10. In main thread: count: 24
  11. In new thread: count: 34
  12. In main thread: count: 35
  13. In new thread: count: 45
  14. In main thread: count: 46
  15. In new thread: count: 56
  16. In main thread: count: 57
  17. In new thread: count: 67
  18. In main thread: count: 68
  19. In new thread: count: 78
  20. In main thread: count: 79
  21. In new thread: count: 89
  22. In main thread: count: 90
  23. In new thread: count: 100

 

参考

POSIX.1-2017

AliOS Things

 

开发者支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号。

更多技术与解决方案介绍,请访问HaaS官方网站https://haas.iot.aliyun.com

 

相关文章
|
2月前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
48 5
|
2月前
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
5月前
|
Unix Linux Ruby
在windows和linux上高效快捷地发布Dash应用
在windows和linux上高效快捷地发布Dash应用
|
5月前
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
438 3
|
5月前
|
存储 监控 Linux
在Linux中,如何进行虚拟化技术的应用?
在Linux中,如何进行虚拟化技术的应用?
|
5月前
|
存储 Linux 开发工具
【Azure App Service】本地Git部署Python Flask应用上云(Azure App Service For Linux)关键错误
【Azure App Service】本地Git部署Python Flask应用上云(Azure App Service For Linux)关键错误
|
5月前
|
存储 监控 Linux
在Linux中,如何进行容器技术的应用?
在Linux中,如何进行容器技术的应用?
|
5月前
|
算法 Ubuntu Linux
在Linux中,对比apt和yum两种包管理器在不同Linux发行版中应用有何区别?
在Linux中,对比apt和yum两种包管理器在不同Linux发行版中应用有何区别?
|
5月前
|
存储 Linux 网络安全
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Linux/Linux Container)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Linux/Linux Container)
|
5月前
|
JavaScript Linux
【Azure App Service for Linux】NodeJS镜像应用启动失败,遇见 RangeError: Incorrect locale information provided
【Azure App Service for Linux】NodeJS镜像应用启动失败,遇见 RangeError: Incorrect locale information provided