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標準的作業系統
其實不只有我們這么想,讓我們一起看看業界的嵌入式實時作業系統是否支持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 {
unsigned int magic;
pthread_attr_t attr;
ktask_t *tid;
void *(*thread_entry)(void *para);
void *thread_para;
ksem_t *join_sem;
unsigned char cancel_state;
volatile unsigned char cancel_type;
volatile unsigned char canceled;
_pthread_cleanup_t *cleanup;
_pthread_environ_t *environ;
void **tls;
void *return_value;
} _pthread_tcb_t;
_pthread_tcb_t是POSIX執行緒內部的核心資料結構,保存著POSIX執行緒的關鍵資料,與內核task的tcb結構相對應,且通過tid相互關聯,POSIX執行緒的關鍵資料型別pthread_t會關聯到這個資料結構上,
- magic 是POSIX執行緒的魔術字,以區別于使用AliOS Things原生的AOS API創建的執行緒,
- attr 執行緒屬性,為POSIX執行緒設定屬性以更細粒度地控制執行緒的行為,如執行緒的堆疊地址,堆疊大小,執行緒的調度策略,調度引數等,
- tid 指向內核task的tcb結構,
- thread_entry 新創建執行緒的執行入口函式的指標,
- thread_para 新創建執行緒的執行入口函式的引數結構指標,
- join_sem 實作執行緒的JOINABLE的信號量,執行緒退出時自身不釋放ptcb資源,由其他執行緒呼叫pthread_join獲取回傳值,并釋放資源,
- cancel_state/cancel_type/canceled 分別表示POSIX執行緒取消狀態(是否使能取消),取消型別(延遲取消、立馬取消),是否取消,目前POSIX執行緒的取消功能暫未實作,
- cleanup 執行緒在退出時要執行的清理函式指標的鏈表,
- tls 存放執行緒私有資料,
- return_value 存放POSIX執行緒的回傳值的指標,
POSIX執行緒的創建與銷毀
使用pthread_create創建POSIX執行緒,
使用pthread_exit銷毀一個POSIX執行緒, 或者從一個執行緒的入口函式回傳,也會走到執行緒的銷毀流程,
下面流程圖為保持邏輯清晰,略去了很多實作細節如例外處理等,
4.2、POSIX條件變數
POSIX條件變數的標準定義:https://pubs.opengroup.org/onlinepubs/9699919799/
關鍵資料結構
typedef struct pthread_cond {
kmutex_t *lock;
int waiting;
int signals;
ksem_t *wait_sem;
ksem_t *wait_done;
pthread_condattr_t attr;
} pthread_cond_t;
pthread_cond_t是實作POSIX條件變數的核心資料結構,
- lock 是保護內部資料的一把mutex鎖,
- waiting 等待這個條件變數的執行緒數,
- signals 已發送信號還未收到確認的數目,
- wait_sem 執行緒等待的信號量,底層內核的信號量原語,
- wait_done 用于發送執行緒與等待執行緒之間握手確認的信號量, 底層內核的信號量原語,
- attr 記錄pthread條件變數的屬性,比如條件變數用到的時鐘clock,
POSIX條件變數的處理
POSIX 條件變數不僅支持觸發單個等待的執行緒,同時還支持廣播(pthread_cond_broadcast),觸發多個等待的執行緒,
4.3、AliOS Things上POSIX介面實作
AliOS Things 支持了pthread,semaphore, message queue, timer, fs等多個模塊的豐富的API,開發者可以利用這些POSIX API,只需要簡單地修改,甚至無需修改,就可以移植Unix/Linux的應用到AliOS Things上,再結合HaaS100的開發板,開發者可以更快速地構建智能設備所需的軟體和硬體,
5、動手試試
5.1、寫一個Linux下基于POSIX介面的應用
下面動手撰寫一個簡單的使用POSIX PTHREAD API的Linux應用,保存為pthread_test.c
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static volatile int count = 1;
pthread_mutex_t count_lock;
void* increase_count(void *arg)
{
while (1) {
sleep(1);
pthread_mutex_lock(&count_lock);
count += 10;
printf("In new thread: count:%d\n", count);
pthread_mutex_unlock(&count_lock);
}
}
int main(int argc, char* argv[])
{
int ret = 0;
pthread_t new_thread;
pthread_mutex_init(&count_lock, NULL);
ret = pthread_create(&new_thread, NULL, increase_count, NULL);
if (ret != 0) {
printf("Error:%s:%d:ret:%d\n", __FILE__, __LINE__, ret);
return -1;
}
while(1) {
sleep(1);
pthread_mutex_lock(&count_lock);
count++;
printf("In main thread: count:%d\n", count);
pthread_mutex_unlock(&count_lock);
}
return 0;
}
在Linux上編譯
gcc pthread_test.c -o pthread_test -lpthread
運行結果如下:
$ ./pthread_test
In main thread: count:2
In new thread: count:12
In main thread: count:13
In new thread: count:23
In main thread: count:24
In new thread: count:34
In main thread: count:35
In new thread: count:45
In main thread: count:46
In new thread: count:56
In main thread: count:57
In new thread: count:67
In main thread: count:68
In new thread: count:78
In main thread: count:79
In new thread: count:89
In main thread: count:90
In new thread: count:100
5.2、移植到AliOS Things上
把上面的pthread_test.c 移植到AliOS Things上,改寫application/example/helloworld_demo 這個demo應用, 把pthread_test.c 的內容替換application/example/helloworld_demo/appdemo.c的全部內容,并做如下2個簡單的修改,
$ diff -ru ~/app/pthread_test.c ~/project/gitee/AliOS-Things/AliOS-Things/application/example/helloworld_demo/appdemo.c
--- ~/app/pthread_test.c 2020-12-10 23:02:56.915084914 +0800
+++ ~/project/gitee/AliOS-Things/AliOS-Things/application/example/helloworld_demo/appdemo.c 2020-12-10 23:06:10.616376591 +0800
@@ -1,6 +1,6 @@
#include <stdio.h>
#include <unistd.h>
-#include <pthread.h>
+#include <posix/pthread.h>
static volatile int count = 1;
pthread_mutex_t count_lock;
@@ -17,7 +17,7 @@
}
-int main(int argc, char* argv[])
+int application_start(int argc, char* argv[])
{
int ret = 0;
pthread_t new_thread;
由上可知,AliOS Things的應用入口是application_start, 不是main, AliOS Things上的posix頭檔案在posix目錄下,如posix/pthread.h,
編譯helloworld_demo
aos make helloworld_demo@haas100 -c config
aos make
下載燒錄并啟動,log如下, 與Linux運行的結果一致,
Welcome to AliOS Things
1592/main_task | sys_init aos_components_init done
1592/main_task | mesh has been opened
1986/mcu_audio | mcu_audio_main exit
[Jan 01 00:00:01.491]<I>ULOG-test sys_init aos_components_init done
In main thread: count:2
In new thread: count:12
In main thread: count:13
In new thread: count:23
In main thread: count:24
In new thread: count:34
In main thread: count:35
In new thread: count:45
In main thread: count:46
In new thread: count:56
In main thread: count:57
In new thread: count:67
In main thread: count:68
In new thread: count:78
In main thread: count:79
In new thread: count:89
In main thread: count:90
In new thread: count:100
移植Linux下應用到AliOS Things之下是不是很簡單,一起來試試吧,
6、參考鏈接
POSIX.1-2017
AliOS Things物聯網作業系統
7、開發者技術支持
如需更多技術支持,可加入釘釘開發者群

更多技術與解決方案介紹,請訪問阿里云AIoT首頁https://iot.aliyun.com/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/236117.html
標籤:其他
