软件工程2021:第2次作业—— 谈谈鸿蒙操作系统

一、概述鸿蒙操作系统

·开发背景

操作系统是电子产品的核心技术,我国对操作系统的需求迫在眉睫,于是华为公司在2012年座谈会上提出鸿蒙系统的研发。

·需求

目前所有应用生态几乎全部基于智能手机平台。虽然智能手表、智能电视、车机,包括其他IoT设备已经出现好几年,但是生态发展非常缓慢,这背后的问题是应用太少,而问题出现最核心的因素是操作系统的高度碎片化。因此,HarmonyOS设计之初,就是面向未来万物互联时代的操作系统,HarmonyOS给所有应用开发者提供分布式编程框架,让大家用自己熟悉的高级语言,只写一次的业务逻辑就能够运行在所有设备上,从而最大限度地实现生态在各个孤立设备上的共享。

·开发历史

2012年9月,在华为“2012诺亚方舟实验室”专家座谈会上,任正非提出要做终端操作系统,以防范于未然。

2017年,鸿蒙OS内核1.0完成技术验证,并逐步开展内核2.0研发。

2018年,鸿蒙内核2.0已被应用于终端TEE。

2019年,鸿蒙OS 1.0版本正式亮相,1.0版本基于开源框架,其关键模块均为自研,同时具备分布式架构、方舟编译器、确定时延引擎、TEE微内核形式化验证以及多终端开发IDE(Beta)。

2021年,鸿蒙操作系统正式开启大规模商用。

·应用场景与发展趋势

鸿蒙操作系统适用于大屏、手表、手机、车机版,开发者将获得模拟器、SDK包以及IDE工具。中国用户对鸿蒙系统的兴趣明显非常高,如果华为的新手机用上了新系统,会有很多用户购买试用。如果鸿蒙能够站稳市场,在市场推广方面三大运营商肯定会采购鸿蒙手机,手机厂家为了吃下采购市场也会去做适配,可能只需要两三年时间鸿蒙的份额就会超过安卓。

二、关于鸿蒙是否套壳的争议 

·什么是创新:

 创新是指以现有的思维模式提出有别于常规或常人思路的见解为导向,利用现有的知识和物质,在特定的环境中,本着理想化需要或为满足社会需求,而改进或创造新的事物、方法、元素、路径、环境,并能获得一定有益效果的行为。虽然目前鸿蒙OS与安卓系统的关系是“剪不断、理还断”,但鸿蒙OS的终极目标并不是超越安卓。包括任正非在内的华为高管多次在公开场合强调,鸿蒙OS是面向万物互联的全场景操作系统,手机只是鸿蒙OS的载体之一,却不是全部。这一点与安卓系统有本质的差别,安卓系统只能在智能手机才有良好的体验,在平板电脑或智能手表等设备上就乏善可陈,当鸿蒙OS连接更多各种各样的设备时,鸿蒙OS的优势就体现出来了,这是iOS和安卓无法比拟的。

·代码复用与创新的关系:

 在人民日报的社论文章当中,首先回应了网络上关于鸿蒙OS“套壳安卓”的说法。鸿蒙OS的部分代码基于ASOP不假,但大部分人把ASOP与安卓系统的关系搞混了。简单的说,华为使用ASOP的代码有两个原因。第一,华为有权使用ASOP的代码,谷歌管不着。第二,鸿蒙OS使用ASOP的代码是基于现状的理智选择。据鸿蒙OS负责人王成录表示,安卓系统的全球开发者超过2000万,苹果iOS的开发者超过2400万。而鸿蒙OS的开发者目前才几百万,现阶段跟安卓和iOS“刚正面”是不现实的。另外使用ASOP的代码、兼容安卓应用是为了保证用户体验。安卓系统已经开发了10几年,消费者已经用习惯了安卓系统,如今贸然更换一个不兼容安卓或者操作逻辑迥异的系统,会造成用户的大量流失。鸿蒙OS就像一个初生的婴儿,循序渐进才是最好的选择,当鸿蒙OS积蓄足够的实力时,就能完全抛开谷歌和ASOP了。

 

三、代码风格分析 

 

好的代码风格1:

 

代码示例:

"···

 pstTaskCB->usTaskStatus &= (~OS_TASK_STATUS_SUSPEND);//清除任务的suspend标志位置
    if (!(OS_CHECK_TASK_BLOCK & pstTaskCB->usTaskStatus) )//若任务的还自在阻塞状态则变为就绪状态 ,并调用 LOS_Schedule()进行调度
    {
        pstTaskCB->usTaskStatus |= OS_TASK_STATUS_READY;
        LOS_PriqueueEnqueue(&pstTaskCB->stPendList, pstTaskCB->usPriority);
        if (g_bTaskScheduled)
        {
            (VOID)LOS_IntRestore(uvIntSave);
            LOS_Schedule();
            return LOS_OK;
        }
        g_stLosTask.pstNewTask = LOS_DL_LIST_ENTRY(LOS_PriqueueTop(), LOS_TASK_CB, stPendList); /*lint !e413*/
    }

    (VOID)LOS_IntRestore(uvIntSave);
    return LOS_OK;

LOS_ERREND:
    (VOID)LOS_IntRestore(uvIntSave);
    return uwErrRet;
}

···"

分析:这个函数的处理过程基本分为两步:

1.改变任务状态:将任务的suspend状态位清掉

2.起用任务调度:如果任务被阻塞,则调起LOS_Schedule进行调度。我们知道完整的LINUX内核是支持将任务指定在某个CPU上运行的,不过鸿蒙OS做为一个微内核的移动操作系统没有继承这些复杂的功能,直接做了减法,实现一个最简模型。

好的代码风格2:

 代码示例:

"···

LITE_OS_SEC_TEXT VOID osSwTmrTask(VOID)
{
    SWTMR_HANDLER_ITEM_P pstSwtmrHandle = (SWTMR_HANDLER_ITEM_P)NULL;
    SWTMR_HANDLER_ITEM_S stSwtmrHandle;
    UINT32 uwRet;

    for ( ; ; )
    {
        uwRet = LOS_QueueRead(m_uwSwTmrHandlerQueue, &pstSwtmrHandle, sizeof(SWTMR_HANDLER_ITEM_P), LOS_WAIT_FOREVER);
        if (uwRet == LOS_OK)
        {
            if (pstSwtmrHandle != NULL)
            {
                stSwtmrHandle.pfnHandler = pstSwtmrHandle->pfnHandler;
                stSwtmrHandle.uwArg = pstSwtmrHandle->uwArg;
                (VOID)LOS_MemboxFree(m_aucSwTmrHandlerPool, pstSwtmrHandle);
                if (stSwtmrHandle.pfnHandler != NULL)
                {
                    stSwtmrHandle.pfnHandler(stSwtmrHandle.uwArg);
                }
            }
        }
    }//end of for
}

···"

分析:

1.节约关键资源:由于每个操作系统的timer都需要一个线程进行回调处理,这对于Tdengine这种数据库动辙几万个timer的应用来说是不可接受的,所以为了节省线程资源,Td要用自己实现的timer之所以要实现自己的定时器是为了节省线程资源。而鸿蒙实现timer则是为了节约硬件定时器资源。

2.最简化设计:两个timer都没有优先级的设定。其中鸿蒙OS做为移动操作系统直接将timer的精度值也舍弃了。

3.使用双链表提高效率:两个timer都使用双链表来存储同一时刻到期的定时器,这样能节省遍历和移动的时间,大大提高效率。

好的代码风格3

 代码示例:

"···

STATIC INLINE VOID *OsMemAllocWithCheck(VOID *pool, UINT32 size, UINT32 intSave)
{
LosMemDynNode *allocNode = NULL;
UINT32 allocSize;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
const VOID *firstNode = (const VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);
INT32 ret;

if (OsMemAllocCheck(pool, intSave) == LOS_NOK) {
return NULL;
}

allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE);
if (allocSize == 0) {
return NULL;
}
retry:

allocNode = OsMemFindSuitableFreeBlock(pool, allocSize);//从内存池中找到合适的内存块
if (allocNode == NULL) {
if (poolInfo->flag & MEM_POOL_EXPAND_ENABLE) {
ret = OsMemPoolExpand(pool, allocSize, intSave);//木有找到就扩展内存池
if (ret == 0) {
goto retry;
}
}
return NULL;
}
if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_ALIGN_SIZE) <= allocNode->selfNode.sizeAndFlag) {
OsMemSplitNode(pool, allocNode, allocSize);//找到了就劈开node
}
OsMemListDelete(&allocNode->selfNode.freeNodeInfo, firstNode);//从空闲双链表中删除该节点
return (allocNode + 1);
}

···"

分析:采用内存池是嵌入式内存管理的一种常用做法,目的是减少申请和释放内存的开销,简单说就是先申请一大块内存,需要时从空闲链表中split,怎么切割鸿蒙就看最佳适应算法(best fit),用完了回收,node进入空闲链表,并从小到大排序,如果相邻两块都是可用内存块就合并。很显然,最佳适应算法(best fit)去带来很多极小块内存碎片的问题。

不的代码风格:

 代码示例:

"···

void *taosProcessSchedQueue(void *param) {
  SSchedMsg    msg;
  SSchedQueue *pSched = (SSchedQueue *)param;

  while (1) {
    if (sem_wait(&pSched->fullSem) != 0) {
      pError("wait %s fullSem failed, errno:%d, reason:%s", pSched->label, errno, strerror(errno));
      if (errno == EINTR) {
        /* sem_wait is interrupted by interrupt, ignore and continue */
        continue;
      }
    }

    if (pthread_mutex_lock(&pSched->queueMutex) != 0)
      pError("lock %s queueMutex failed, reason:%s", pSched->label, strerror(errno));

    msg = pSched->queue[pSched->fullSlot];
    memset(pSched->queue + pSched->fullSlot, 0, sizeof(SSchedMsg));
    pSched->fullSlot = (pSched->fullSlot + 1) % pSched->queueSize;//从队尾取出消息不断处理

    if (pthread_mutex_unlock(&pSched->queueMutex) != 0)
      pError("unlock %s queueMutex failed, reason:%s
", pSched->label, strerror(errno));

    if (sem_post(&pSched->emptySem) != 0)
      pError("post %s emptySem failed, reason:%s
", pSched->label, strerror(errno));

    if (msg.fp)
      (*(msg.fp))(&msg);
    else if (msg.tfp)
      (*(msg.tfp))(msg.ahandle, msg.thandle);
  }
}

···"

分析:从其循环处理任务的函数(taosProcessSchedQueue),可以看出它只是队尾不断取出任务进行循环处理,而没有优化级调整排序的过程。

 

 

posted @ 2021-09-15 10:00  辣椒怪兽  阅读(367)  评论(1编辑  收藏  举报