往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- 【OpenHarmony】鸿蒙南向开发保姆级知识点汇总~
- OpenHarmony源码分析之分布式软总线:trans_service模块(1)/认证通道管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(2)/会话管理之新会话
- OpenHarmony源码分析之分布式软总线:trans_service模块(3)/线程同步锁管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(4)/TCP会话管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(5)/TCP会话管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(6)/TCP会话管理
- OpenHarmony源码分析之分布式软总线:trans_service/message.c文件分析
- OpenHarmony源码分析之分布式软总线:trans_service/tcp_session.c
- OpenHarmony源码分析之分布式软总线:msg_get_deviceid.c文件分析
- OpenHarmony源码分析之分布式软总线:os_adapter模块解析
- 持续更新中……
一、概述
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;
}
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: