📌往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)
①📖 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
②📖嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
③📖 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
④📖 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
⑤📖 记录一场鸿蒙开发岗位面试经历~
⑥📖 持续更新中……
一、概述
os_adapter模块是操作系统适配层。HarmonyOS的操作系统底层可以是:HarmonyOS micro kernel,Linux kernel,且 Lite OS将成为一个完整的鸿蒙微内核架构。鸿蒙系统内部各个模块内部使用的函数需要支持针对不同版本平台的适配,体现各部分解耦的模块化设计思想,针对不同的硬件设备,组合成最适合该设备的OS。当前版本的鸿蒙系统的os_adapter模块针对Lite OS内核和Linux内核实现了互斥锁和消息队列的适配。下面分别对两种内核的适配源码进行分析。
二、源码分析
- 基于LiteOS内核的os_adapter.c文件解析。
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "os_adapter.h"
#include "lwip/sockets.h"
/*创建并初始化互斥锁*/
MutexId MutexInit(void)
{
return (MutexId)osMutexNew(NULL);//创建并初始化一个新的互斥对象,并在出现错误时返回指向互斥对象标识符的指针或NULL。CMSIS-RTOS2标准
}
/*申请互斥锁*/
void MutexLock(MutexId mutex)
{
if (mutex == NULL) {
return;
}
osMutexAcquire(mutex, osWaitForever);//等待直到参数mutex指定的互斥对象变为可用。如果没有其他线程获得互斥锁,该函数会立即返回并阻塞互斥锁对象。CMSIS-RTOS2标准
}
/*释放互斥锁*/
void MutexUnlock(MutexId mutex)
{
if (mutex == NULL) {
return;
}
osMutexRelease(mutex);//释放由参数mutex指定的互斥锁。当前等待此互斥锁的其他线程将被置于READY状态。CMSIS-RTOS2标准
}
/*关闭套接字fd*/
void CloseSocket(int *fd)
{
if (fd == NULL) {
return;
}
if (*fd >= 0) {
closesocket(*fd);
*fd = -1;
}
}
/*
函数功能:向消息队列中写入一条消息
函数参数:
queueID:消息队列id
bufferAddr:要写入的消息体的首地址
bufferSize:要写入的消息体大小
函数返回值:
成功:返回0
失败:返回-1
*/
int WriteMsgQue(unsigned int queueID, const void *bufferAddr, unsigned int bufferSize)
{
if (bufferAddr == NULL) {//健壮性检查
return -1;
}
(void)bufferSize;//此处未使用到这个参数,但为了避免编译器发出警告,做此处理
return osMessageQueuePut((osMessageQueueId_t)queueID, (VOID*)bufferAddr, 0, 0);//将bufferAddr指向的消息放入参数queueID指定的消息队列中。CMSIS-RTOS2的消息队列写入方法
}
/*
函数功能:创建并初始化消息队列
函数参数:
queueName:消息队列名称,传入参数
len:消息队列的最大消息数
queueID:消息队列id,传出参数
flags:标志
maxMsgSize:消息队列中每个消息的最大字节数
函数返回值:
成功:返回0
失败:返回-1
*/
int CreateMsgQue(const char *queueName,
unsigned short len, unsigned int *queueID,
unsigned int flags, unsigned short maxMsgSize)
{
osMessageQueueId_t id;//定义消息队列id
if (queueID == NULL) {
return -1;
}
(void)queueName;//此处未使用到这个参数,但为了避免编译器发出警告,做此处理
(void)flags;//此处未使用到这个参数,但为了避免编译器发出警告,做此处理
id = osMessageQueueNew(len, maxMsgSize, NULL);//创建并初始化一个消息队列对象。如果出现错误,该函数将返回消息队列对象标识符或NULL。CMSIS-RTOS2标准
if (NULL == id) {
return -1;
}
*queueID = (unsigned int)id;//赋值给传出参数
return 0;
}
/*删除queueID指定的消息队列*/
int DeleteMsgQue(unsigned int queueID)
{
return osMessageQueueDelete((osMessageQueueId_t)queueID);//删除由参数queueID指定的消息队列对象。它释放为消息队列处理获得的内部内存。CMSIS-RTOS2标准
}
/*
函数功能:从消息队列中读取消息
函数参数:
queueID:消息队列id
bufferAddr:用于保存消息体的缓冲区首地址
bufferSize:用于保存消息体的缓冲区大小
函数返回值:
成功:返回0
失败:返回-1
*/
int ReadMsgQue(unsigned int queueID,
void *bufferAddr, unsigned int *bufferSize)
{
if (bufferAddr == NULL || bufferSize == NULL) {//健壮性检查
return -1;
}
return osMessageQueueGet((osMessageQueueId_t)queueID, bufferAddr, NULL, osWaitForever);//从参数queueID指定的消息队列中检索消息,并将其保存到参数bufferAddr指向的缓冲区中。CMSIS-RTOS2标准
}
/*软总线权限检查*/
int SoftBusCheckPermission(const char* permissionName)
{
if (permissionName == NULL) {
return -1;
}
return 0;
}
- 基于Linux内核的os_adapter.c文件解析。
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "os_adapter.h"
#include <errno.h>
#include <mqueue.h>
#include <pthread.h>
#include <unistd.h>
/*创建并初始化互斥锁*/
MutexId MutexInit(void)
{
pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));//定义一个互斥锁对象
if (mutex == NULL) {
return NULL;
}
(void)pthread_mutex_init(mutex, NULL);//初始化该互斥锁。POSIX标准
return (MutexId)mutex;
}
/*申请互斥锁资源*/
void MutexLock(MutexId mutex)
{
if (mutex == NULL) {
return;
}
pthread_mutex_lock((pthread_mutex_t *)mutex);//申请互斥锁资源。POSIX标准
}
/*释放互斥锁资源*/
void MutexUnlock(MutexId mutex)
{
if (mutex == NULL) {
return;
}
pthread_mutex_unlock((pthread_mutex_t *)mutex);//释放互斥锁资源。POSIX标准
}
/*关闭套接字fd,即关闭连接*/
void CloseSocket(int *fd)
{
if (fd == NULL) {
return;
}
if (*fd >= 0) {
close(*fd);
*fd = -1;
}
}
/*
函数功能:创建并初始化消息队列
函数参数:
queueName:消息队列名称,传入参数
len:消息队列的最大消息数
queueID:消息队列id,传出参数
flags:标志,0或O_NONBLOCK,用来表示是否阻塞
maxMsgSize:消息队列中每个消息的最大字节数
函数返回值:
成功:返回0
失败:返回-1
*/
int CreateMsgQue(const char *queueName,
unsigned short len, unsigned int *queueID,
unsigned int flags, unsigned short maxMsgSize)
{
if (queueName == NULL || queueID == NULL) {//健壮性检查
return -1;
}
//定义并初始化一个消息队列属性对象
struct mq_attr newAttr = {0};
newAttr.mq_flags = flags;
newAttr.mq_maxmsg = len;
newAttr.mq_msgsize = maxMsgSize;
int mqd = mq_open(queueName, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR, &newAttr);//打开或创建一个消息队列。POSIX标准
if (mqd < 0) {
return -1;
}
*queueID = mqd;
return 0;
}
/*
函数功能:向消息队列中写入一条消息
函数参数:
queueID:消息队列id
bufferAddr:要写入的消息体的首地址
bufferSize:要写入的消息体大小
函数返回值:
成功:返回0
失败:返回-1
*/
int WriteMsgQue(unsigned int queueID,
const void *bufferAddr, unsigned int bufferSize)
{
if (bufferAddr == NULL) {
return -1;
}
int ret = mq_send(queueID, bufferAddr, bufferSize, 0);//向消息队列中写入一条消息。POSIX标准
if (ret != 0) {
return -1;
}
return 0;
}
/*删除消息队列*/
int DeleteMsgQue(unsigned int queueID)
{
return mq_close(queueID);
}
/*
函数功能:从消息队列中读取消息
函数参数:
queueID:消息队列id
bufferAddr:用于保存消息体的缓冲区首地址
bufferSize:用于保存消息体的缓冲区大小
函数返回值:
成功:返回0
失败:返回-1
*/
int ReadMsgQue(unsigned int queueID,
void *bufferAddr, unsigned int *bufferSize)
{
if (bufferAddr == NULL || bufferSize == NULL) {
return -1;
}
unsigned int readSize = *bufferSize;
unsigned int receiveSize = mq_receive(queueID, bufferAddr, readSize, 0);//从消息队列中读取消息。POSIX标准
if (receiveSize != readSize) {
return -1;
}
*bufferSize = receiveSize;
return 0;
}
/*软总线权限检查:成功返回0,失败返回-1*/
int SoftBusCheckPermission(const char* permissionName)
{
if (permissionName == NULL) {
return -1;
}
if (CheckSelfPermission(permissionName) != GRANTED) {
SOFTBUS_PRINT("[SOFTBUS] CheckSelfPermission fail\n");
return -1;
}
return 0;
}