清空記錄
歷史記錄
取消
清空記錄
歷史記錄
編程入門[Hello,OpenHarmony]
#include
#include "ohos_init.h"
void hello(void){
printf("Hello,OpenHarmony!");
}
SYS_RUN(hello);
第一次操作的伙伴們可能會在引入”ohos_init.h“庫時報錯,面對這個問題我們只需要修改我們的include path即可,一般我們直接在目錄下的 .vscode/c_cpp_properties.json文件中直接修改includePath
sudo apt install mlocate
sudo updatedb
locate ohos_init.h
找到我們源碼根目錄下 include路徑下的ohos_init.h文件
static_library("sayHello"){
sources = [
"hello.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include"
]
}
static_library表示我們編寫的靜態(tài)模塊,名為"sayHello", sources表示我們要編譯的源碼,include_dirs表示我們引入的庫,這里的雙斜杠就代表我們的源碼根目錄,”/commonlibrary/utils_lite/include“就是我們ohos_init.h的所在目錄
這表示我們的程序?qū)?zhí)行hello_demo樣例中的sayHello模塊
至此編碼完成了編碼入門,下面就具體介紹OpenHarmony的內(nèi)核編程。
內(nèi)核
我們可以看到最底層叫做內(nèi)核層,有Linux,LiteOS等。內(nèi)核在整個架構(gòu),或者操作系統(tǒng)中起到一個核心作用,他負責管理計算機系統(tǒng)內(nèi)的資源和硬件設(shè)備,提供給頂層的應用層一個統(tǒng)一規(guī)范的接口,從而使得整個系統(tǒng)能夠完成應用與硬件的交互。
這些都是進程,一個進程又由多個線程組成。那么CPU,內(nèi)存,硬盤,網(wǎng)絡這些硬件層面資源是怎么合理分配到我們軟件的各個進程中呢?這就是內(nèi)核幫助我們完成的事情,我們并不關(guān)心我們設(shè)備上的應用在哪里執(zhí)行,如何分配資源,內(nèi)核會完成這些事情。我們?nèi)粘Ec軟件交互,而內(nèi)核會幫助我們完成軟件和硬件的交互。
下面重點介紹KAL抽象層 和 基礎(chǔ)內(nèi)核的操作
內(nèi)核編程
typedef struct {
/** Thread name */
const char *name;
/** Thread attribute bits */
uint32_t attr_bits;
/** Memory for the thread control block */
void *cb_mem;
/** Size of the memory for the thread control block */
uint32_t cb_size;
/** Memory for the thread stack */
void *stack_mem;
/** Size of the thread stack */
uint32_t stack_size;
/** Thread priority */
osPriority_t priority;
/** TrustZone module of the thread */
TZ_ModuleId_t tz_module;
/** Reserved */
uint32_t reserved;
} osThreadAttr_t;
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
osStatus_t osThreadTerminate (osThreadId_t thread_id);
typedef enum {
/** Operation completed successfully */
osOK = 0,
/** Unspecified error */
osError = -1,
/** Timeout */
osErrorTimeout = -2,
/** Resource error */
osErrorResource = -3,
/** Incorrect parameter */
osErrorParameter = -4,
/** Insufficient memory */
osErrorNoMemory = -5,
/** Service interruption */
osErrorISR = -6,
/** Reserved. It is used to prevent the compiler from optimizing enumerations. */
osStatusReserved = 0x7FFFFFFF
} osStatus_t;
回調(diào)函數(shù)怎么寫?當然是結(jié)合我們的任務,每間隔0.1秒,輸出“Hello,OpenHarmony”,1秒后終止。講到這里,代碼的整體邏輯是不是就清晰了很多,直接上完整代碼。
#include
#include "ohos_init.h"
// CMSIS
#include "cmsis_os2.h"
// POSIX
#include
// 線程回調(diào)函數(shù)
void printThread(void *args){
(void)args;
while(1){
printf("Hello,OpenHarmony!\r\n");
// 休眠0.1秒
osDelay(10);
}
}
void threadTest(void){
// 創(chuàng)建線程
osThreadAttr_t attr;
attr.name = "mainThread";
// 線程
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024;
attr.priority = osPriorityNormal;
// 將線程啟動
osThreadId_t tid = osThreadNew((osThreadFunc_t)printThread, NULL, &attr);
if(tid == NULL){
printf("[Thread Test] Failed to create printThread!\r\n");
}
// 休眠5秒
osDelay(500);
// 終止線程
osStatus_t status = osThreadTerminate(tid);
printf("[Thread Test] printThread stop, status = %d.\r\n", status);
}
APP_FEATURE_INIT(threadTest);
static_library("thread_demo"){
sources = [
"singleThread.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include",
"http://device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis"
]
}
注意的是,這次的寫法與上次不同,是因為筆者的樣例文件名和靜態(tài)模塊的名字是一樣的就可以簡寫。
osThreadId_t newThread(char *name, osThreadFunc_t func, void *arg){
// 定義線程和屬性
osThreadAttr_t attr = {
name, 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0
};
// 創(chuàng)建線程
osThreadId_t tid = osThreadNew(func, arg, &attr);
if(tid == NULL){
printf("[newThread] osThreadNew(%s) failed.\r\n", name);
}
return tid;
}
線程部分先體會到這里,想要探索更過線程相關(guān)的API,筆者這里提供了API網(wǎng)站,供大家參考學習。
軟件定時器
osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr);
typedef enum {
/** One-shot timer */
osTimerOnce = 0,
/** Repeating timer */
osTimerPeriodic = 1
} osTimerType_t;
osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks);
osStatus_t osTimerStop (osTimerId_t timer_id);
osStatus_t osTimerDelete (osTimerId_t timer_id);
#include
#include "ohos_init.h"
// CMSIS
#include "cmsis_os2.h"
// POSIX
#include
// 為操作軟件的時間
static int times = 0;
// 軟件定時器回調(diào)函數(shù)
void timerFunction(void){
times++;
printf("[Timer Test] Timer is Running, times = %d.\r\n", times);
}
// 主函數(shù)
void timerMain(void){
// 創(chuàng)建軟件定時器
osTimerId_t tid = osTimerNew(timerFunction, osTimerPeriodic, NULL, NULL);
if(tid == NULL){
printf("[Timer Test] Failed to create a timer!\r\n");
return;
} else {
printf("[Timer Test] Create a timer success!\r\n");
}
// 啟動軟件定時器,每1秒執(zhí)行一次回調(diào)函數(shù)
osStatus_t status = osTimerStart(tid, 100);
// 當超過三個周期位操作軟件時,關(guān)閉軟件
while(times <= 3){
osDelay(100);
}
// 停止軟件定時器
status = osTimerStop(tid);
// 刪除軟件定時器
status = osTimerDelete(tid);
printf("[Timer Test] Time Out!\r\n");
}
void TimerTest(void){
// 創(chuàng)建測試線程
osThreadAttr_t attr;
attr.name = "timerMain";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 0U;
attr.priority = osPriorityNormal;
// 啟動測試線程
osThreadId_t tid = osThreadNew((osThreadFunc_t)timerMain, NULL, &attr);
if(tid == NULL){
printf("[Timer Test] Failed to created timerMain!\r\n");
}
}
APP_FEATURE_INIT(TimerTest);
static_library("timer_demo"){
sources = [
"timer.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include",
"http://device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis"
]
}
typedef struct {
const char *name;
uint32_t attr_bits;
void *cb_mem;
uint32_t cb_size;
void *stack_mem;
uint32_t stack_size;
osPriority_t priority;
TZ_ModuleId_t tz_module;
uint32_t reserved;
} osThreadAttr_t;
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
sStatus_t status = osThreadTerminate(osThreadId_t tid);
if(count > 0){
count--;
}
售票的邏輯很簡單,只要票數(shù)大于零,還有票能賣,那就在此基礎(chǔ)上減掉一。問題就在于,兩個線程同時在count = 1的時候通過了if判斷,都執(zhí)行的count--;那么就會出現(xiàn)了count = -1,也就是票數(shù)為負 的bug結(jié)果。
typedef struct {
/** Mutex name */
const char *name;
/** Reserved attribute bits */
uint32_t attr_bits;
/** Memory for the mutex control block */
void *cb_mem;
/** Size of the memory for the mutex control block */
uint32_t cb_size;
} osMutexAttr_t;
osMutexId_t osMutexNew(const osMutexAttr_t *attr);
osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout);
傳入互斥鎖id,設(shè)置我們的延遲時間,當線程獲取到我們的互斥鎖時,返回的狀態(tài)是osOK。
typedef enum {
/** Operation completed successfully */
osOK = 0,
/** Unspecified error */
osError = -1,
/** Timeout */
osErrorTimeout = -2,
/** Resource error */
osErrorResource = -3,
/** Incorrect parameter */
osErrorParameter = -4,
/** Insufficient memory */
osErrorNoMemory = -5,
/** Service interruption */
osErrorISR = -6,
/** Reserved. It is used to prevent the compiler from optimizing enumerations. */
osStatusReserved = 0x7FFFFFFF
} osStatus_t;
osStatus_t osMutexRelease(osMutexId_t mutex_id);
當我們的線程執(zhí)行完業(yè)務后需要把鎖釋放出來,讓別的線程獲取鎖,執(zhí)行業(yè)務。當然這個過程是線程之間的競爭,一個線程可能一直得不到鎖,一個線程也可能剛釋放鎖又獲得鎖,我們可以添加休眠操作,提高鎖在各個線程間的分配。
#include
#include
#include "ohos_init.h"
#include "cmsis_os2.h"
// 模擬動物園門票數(shù)
static int count = 100;
// 售票業(yè)務線程
void outThread(void *args){
// 獲取互斥鎖
osMutexId_t *mid = (osMutexId_t *)args;
// 每個線程都在不停地買票
while(1){
// 獲取鎖,進入業(yè)務流程
if(osMutexAcquire(*mid, 100) == osOK){
if(count > 0){
count--;
// 設(shè)置提示信息
printf("[Mutex Test] Thread %s get a value, the less is %d.\r\n", osThreadGetName(osThreadGetId()), count);
} else {
// 告知這些線程已經(jīng)沒有門票賣了,線程結(jié)束
printf("[Mutex Test] The value is out!\r\n");
osThreadTerminate(osThreadGetId());
}
}
// 釋放鎖
osMutexRelease(*mid);
osDelay(5);
}
}
// 創(chuàng)建線程封裝
osThreadId_t createThreads(char *name, osThreadFunc_t func, void *args){
osThreadAttr_t attr = {
name, 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0
};
osThreadId_t tid = osThreadNew(func, args, &attr);
return tid;
}
// 主函數(shù)實現(xiàn)多線程的創(chuàng)建,執(zhí)行買票業(yè)務
void mutexMain(void){
// 創(chuàng)建互斥鎖
osMutexAttr_t attr = {0};
// 獲取互斥鎖的id
osMutexId_t mid = osMutexNew(&attr);
if(mid == NULL){
printf("[Mutex Test] Failed to create a mutex!\r\n");
}
// 創(chuàng)建多線程
osThreadId_t tid1 = createThreads("Thread_1", (osThreadFunc_t)outThread, &mid);
osThreadId_t tid2 = createThreads("Thread_2", (osThreadFunc_t)outThread, &mid);
osThreadId_t tid3 = createThreads("Thread_3", (osThreadFunc_t)outThread, &mid);
osDelay(1000);
}
// 測試線程
void MainTest(void){
osThreadId_t tid = createThreads("MainTest", (osThreadFunc_t)mutexMain, NULL);
}
APP_FEATURE_INIT(MainTest);
static_library("mutex_demo"){
sources = [
"mutex.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include",
"http://device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis"
]
}
結(jié)果展示
if(osMutexAcquire(*mid, 100) == osOK){
if(count > 0){
count--;
printf("[Mutex Test] Thread %s get a value, the less is %d.\r\n", osThreadGetName(osThreadGetId()), count);
} else {
printf("[Mutex Test] The value is out!\r\n");
osThreadTerminate(osThreadGetId());
}
}
結(jié)果展示如下:
osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout);
#define osWaitForever 0xFFFFFFFFU
osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id);
3.源碼編寫
#include
#include
#include "ohos_init.h"
#include "cmsis_os2.h"
// 售票口 4
#define OUT_NUM 4
// 檢票口 2
#define IN_NUM 2
// 信號量
osSemaphoreId_t sid;
// 待檢票人數(shù)
static int people = 0;
// 售票業(yè)務
void outThread(void *args){
// 獲取互斥鎖
osMutexId_t *mid = (osMutexId_t *)args;
while(1){
if(osMutexAcquire(*mid, 100) == osOK){
// 賣一張票,帶檢票的人數(shù)就會加一位
people++;
printf("[SEMAPHORE TEST] out, people: %d.\r\n", people);
}
osMutexRelease(*mid);
osDelay(50);
}
}
// 檢票業(yè)務
void inThread(void *args){
// 獲取信號量
osSemaphoreAcquire(sid, osWaitForever);
while(1){
if(people > 0){
people--;
printf("[SEMAPHORE TEST] in, people: %d.\r\n", people);
}
osSemaphoreRelease(sid);
osDelay(100);
}
}
// 創(chuàng)建線程封裝
osThreadId_t createThreads(char *name, osThreadFunc_t func, void *args){
osThreadAttr_t attr = {
name, 0, NULL, 0, NULL, 1024 * 2, osPriorityNormal, 0, 0
};
osThreadId_t tid = osThreadNew(func, args, &attr);
return tid;
}
// 主線程
void SemaphoreMain(void){
// 創(chuàng)建信號量
sid = osSemaphoreNew(IN_NUM, IN_NUM, NULL);
// 創(chuàng)建互斥鎖
osMutexAttr_t attr = {0};
// 獲取互斥鎖的id
osMutexId_t mid = osMutexNew(&attr);
// 創(chuàng)建售票線程
for(int i = 0; i < OUT_NUM; i++){
createThreads("", (osThreadFunc_t)outThread, &mid);
}
// 創(chuàng)建檢票線程
for(int i = 0; i < IN_NUM; i++){
createThreads("", (osThreadFunc_t)inThread, NULL);
}
}
// 測試函數(shù)
void MainTest(){
createThreads("MainTest", (osThreadFunc_t)SemaphoreMain, NULL);
}
APP_FEATURE_INIT(MainTest);
static_library("semaphore_demo"){
sources = [
"semaphore.c"
]
include_dirs = [
"http://utils/native/lite/include",
]
}
#### 消息隊列API
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id);
3.編寫源碼
#include
#include
#include "ohos_init.h"
#include "cmsis_os2.h"
// 定義消息隊列的大小
#define QUEUE_SIZE 15
// 定義請求數(shù)量
#define REQ_SIZE 10
// 定義消息的結(jié)構(gòu)
typedef struct{
osThreadId_t tid;
} message_queue;
// 創(chuàng)建消息隊列id
osMessageQueueId_t qid;
// 模擬發(fā)送業(yè)務
void sendThread(void){
// 定義一個消息結(jié)構(gòu)
message_queue sentry;
sentry.tid = osThreadGetId();
osDelay(100);
// 消息入隊
osMessageQueuePut(qid, (const void*)&sentry, 0, osWaitForever);
// 設(shè)置提示信息
printf("[MESSAGEQUEUE TEST] %d send a message.\r\n", sentry.tid);
}
// 模擬處理業(yè)務
void receiverThread(void){
// 定義一個消息結(jié)構(gòu)
message_queue rentry;
int less = 5;
while(less > 0){
osMessageQueueGet(qid, (void *)&rentry, NULL, osWaitForever);
less--;
printf("[MESSAGEQUEUE TEST] %d get a product, less = %d.\r\n", rentry.tid, less);
osDelay(5);
}
printf("[MESSAGEQUEUE TEST] over!\r\n");
}
// 創(chuàng)建線程封裝
osThreadId_t createThreads(char *name, osThreadFunc_t func, void *args){
osThreadAttr_t attr = {
name, 0, NULL, 0, NULL, 1024 * 2, osPriorityNormal, 0, 0
};
osThreadId_t tid = osThreadNew(func, args, &attr);
return tid;
}
// 主線程
void MessageQueueMain(void){
// 創(chuàng)建一個消息隊列
qid = osMessageQueueNew(QUEUE_SIZE, sizeof(message_queue), NULL);
// 創(chuàng)建發(fā)送線程
for(int i = 0; i < REQ_SIZE; i++){
createThreads("", (osThreadFunc_t)sendThread, NULL);
}
osDelay(5);
// 創(chuàng)建接收線程
createThreads("", (osThreadFunc_t)receiverThread, NULL);
osDelay(500);
// 刪除消息隊列
osMessageQueueDelete(qid);
}
// 測試函數(shù)
void MainTest(){
createThreads("MainTest", (osThreadFunc_t)MessageQueueMain, NULL);
}
APP_FEATURE_INIT(MainTest);
static_library("queue_demo"){
sources = [
"queue.c",
]
include_dirs = [
"http://utils/native/lite/include",
]
}
結(jié)束語