How to easily port Linux applications to AliOS Things

1 Introduction

In recent years, a large number of smart devices have entered people's lives, such as smart speakers, various payment devices, and advertising machines of various sizes on the streets and alleys. Most of these devices still use Linux, and most of the devices with screens use Android, which causes them to use higher-cost hardware.

 

AliOS Things is an embedded real-time operating system developed by Alibaba Cloud IoT for use in IoT smart devices. It is the operating system carried by HaaS100 . At present, AliOS Things + applet framework can replace Linux or even Android, greatly reducing the cost of equipment. But the mature and stable frameworks on Linux (including Android), especially the audio and video processing framework, graphics rendering, etc., if they can be used, and then adapted and optimized, there is no need to repeat the wheel, it is not beautiful.

 

How to easily port these excellent frameworks such as Unix/Linux to AliOS Things? Supporting POSIX is a weapon to achieve this goal.

 

2. What is POSIX

POSIX (Portable Operating System Interface) is a standard formulated by the IEEE organization to maintain the compatibility of applications between different operating systems. It mainly includes a complete set of application operating environment such as API, Shell and Utility . Widely used in UNIX/LINUX operating systems, and some embedded operating systems (such as Zephyr, VxWorks, QNX, Fuchsia, FreeRTOS, RT-Thread, AliOS Things ).

 

The POSIX standard is also known as IEEE 1003, ISO/IEC 9945. The current standard developer is the Austin Group, which is a joint organization of IEEE, Open Group, and ISO/IEC. The latest version of the current POSIX standard is POSIX.1-2017. At the beginning, the POSIX standard (IEEE 1003) was divided into different subsets, of which IEEE 1003.13 was still in effect. IEEE 1003.13 is a standard formulated for the embedded field. According to the size of the range, it is divided into 4 different profiles, PSE51, PSE52, PSE53 and PSE54. The relationship is shown in the figure below.

image.png

 

3. Why do you need POSIX

As an embedded real-time operating system in the Internet of Things, why does AliOS Things support the POSIX standard? In addition to solving the problems introduced in the preface, is there any other purpose? This chapter will give a comprehensive explanation.

 

3.1, the core problem solved by POSIX

Software ecology

The software ecology is the core of the survival of an OS, but the construction of an OS software ecology cannot be eager for success. It requires years of accumulation and precipitation. Obviously, the ecology of AliOS Things is still immature, while the ecology of Linux has become very powerful after decades of precipitation. Support POSIX can

  • Compatible with Unix/Linux software ecology.
  • Compatible with the software ecology of embedded systems that support POSIX standards (such as FreeRTOS).

 

standard

  • The API model is defined by an international authoritative organization, has been widely used and verified, and is mature and stable.

 

Easy to use

  • The API is familiar to the majority of developers, reducing the cost of learning for developers.
  • Each API has standardized documentation in detail, which is convenient for query and use.
  • Provide standard interfaces for the internal components of AliOS Things to facilitate the use and support of multiple platforms such as porting to Linux.

 

3.2. Other operating systems that support POSIX standards

In fact, we are not the only ones who think so. Let us take a look at whether the embedded real-time operating system in the industry supports the POSIX standard.

 

VxWorks

As a relatively old embedded real-time operating system, VxWorks is widely used in many fields, such as aerospace, industrial control and other fields that require high real-time performance. It also attaches great importance to the support of the POSIX standard, all of which support PSE52 Standard + BSD Socket. And passed the official PSE52 certification.

 

QNX

As an embedded real-time operating system widely used in the automotive field and a relatively successful commercial micro-kernel operating system, QNX also attaches great importance to the support of the POSIX standard, and all of it supports the PSE52 standard + BSD Socket.

 

Fuchsia

As a new microkernel operating system designed and developed by Google, Fuchsia also supports the POSIX standard.

 

FreeRTOS

Although FreeRTOS is mainly applied to MCU devices with relatively limited resources, it also implements some APIs in the PSE52 range.

 

RT-Thread

RT-Thread is mainly used in smart devices in the field of Internet of Things. It also pays more attention to the support of the POSIX standard and implements most of the APIs in the PSE52 range.

 

The long-term goal of AliOS Things to support POSIX is to achieve the latest version of POSIX.1. For example, it is currently POSIX.1-2017. It has a total of 1191 APIs, the number is very large, but there are many APIs that are not frequently used, so the short-term goal It is the API that implements PSE52 + Networking standard + API required in the project.

 

4. Design and implementation of POSIX

As the interface layer between the kernel and the application, POSIX involves many aspects of the kernel. The following only takes POSIX threads and POSIX condition variables as examples to introduce its design and implementation. The code of POSIX components is located in core/osal/posix/, and the header files are located in include/posix/.

4.1, POSIX thread

Key data structure

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 is the core data structure inside the POSIX thread. It saves the key data of the POSIX thread. It corresponds to the tcb structure of the kernel task and is related to each other through tid. The key data type pthread_t of POSIX threads will be associated with this data structure.

  • Magic is the magic word for POSIX threads to distinguish them from threads created using AliOS Things' native AOS API.
  • attr thread attributes, set attributes for POSIX threads to control the behavior of the thread more fine-grained. Such as thread stack address, stack size, thread scheduling strategy, scheduling parameters, etc.
  • tid points to the tcb structure of the kernel task.
  • thread_entry The pointer to the execution entry function of the newly created thread.
  • thread_para The parameter structure pointer of the execution entry function of the newly created thread.
  • join_sem implements the JOINABLE semaphore of the thread. When the thread exits, it does not release the ptcb resource. Other threads call pthread_join to obtain the return value and release the resource.
  • Cancel_state/cancel_type/canceled respectively indicate the cancellation status of the POSIX thread (whether cancellation is enabled), the cancellation type (delayed cancellation, immediate cancellation), and whether to cancel. The cancellation function of POSIX threads has not yet been implemented.
  • A linked list of cleanup function pointers to be executed when the thread exits.
  • tls stores thread private data.
  • return_value is a pointer to the return value of the POSIX thread.

 

POSIX thread creation and destruction

Use pthread_create to create POSIX threads.

Using pthread_exit to destroy a POSIX thread, or returning from the entry function of a thread, will also go to the thread destruction process.

To keep the logic clear, the following flowchart omits many implementation details such as exception handling.

posix1.png

 

4.2, POSIX condition variables

The standard definition of POSIX condition variables: https://pubs.opengroup.org/onlinepubs/9699919799/

Key data structure

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 is the core data structure that implements POSIX condition variables.

  • lock is a mutex lock to protect internal data.
  • waiting The number of threads waiting for this condition variable.
  • signals The number of signals sent but not confirmed.
  • wait_sem The semaphore that the thread waits for, the semaphore primitive of the underlying kernel.
  • wait_done is used to send the semaphore for the handshake confirmation between the thread and the waiting thread, the semaphore primitive of the underlying kernel.
  • attr records the attributes of pthread condition variables, such as the clock used by the condition variables.

 

POSIX condition variable processing

pthread-cond.png

POSIX condition variables not only support triggering a single waiting thread, but also support broadcasting (pthread_cond_broadcast) to trigger multiple waiting threads.

 

4.3, POSIX interface implementation on AliOS Things

AliOS Things supports rich APIs of multiple modules such as pthread, semaphore, message queue, timer, fs, etc. Developers can use these POSIX APIs to simply modify, or even without modification, to port Unix/Linux applications to On AliOS Things. Combined with the HaaS100 development board, developers can more quickly build the software and hardware required for smart devices.

 

5. Try it yourself

5.1. Write an application based on POSIX interface under Linux

Let’s write a simple Linux application using POSIX PTHREAD API and save it as 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;
}

Compile on Linux

gcc pthread_test.c -o pthread_test -lpthread

The results are as follows:

$ ./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. Ported to AliOS Things

Port the above pthread_test.c to AliOS Things, and rewrite the demo application application/example/helloworld_demo. Replace the content of pthread_test.c with the entire content of application/example/helloworld_demo/appdemo.c, and make the following two simple modifications.

$ 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;

It can be seen from the above that the application entry of AliOS Things is application_start, not main. The posix header file on AliOS Things is in the posix directory, such as posix/pthread.h.

 

Compile helloworld_demo

aos make helloworld_demo@haas100 -c config
aos make

Download, burn and start, the log is as follows, consistent with the result of Linux running.

             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

Is it easy to transplant applications from Linux to AliOS Things? Let's try it together.

 

6. Reference link

POSIX.1-2017

AliOS Things Internet of Things Operating System

 

7. Developer technical support

If you need more technical support, you can join the Dingding Developer Group

For more technology and solution introduction, please visit the Aliyun AIoT homepage https://iot.aliyun.com/

Guess you like

Origin blog.csdn.net/HaaSTech/article/details/111244885