鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略

这篇具有很好参考价值的文章主要介绍了鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【找到了一种简单易懂的实验实现方式,适合基础较薄弱的同学,见第二部分】

最终效果如下:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

依次创建了3个任务线程,以One、Two、Three指代,时间分别为15秒、30秒、10秒。

如果按生成顺序输出应该是:One->Two->Three,但我们修改了OsPriQueueEnqueue函数,由原先的“先进先出”,转化为“短作业优先”,所以实际的执行顺序变成了Three->One->Two,满足实验所要求的“短作业优先”要求。

一、实验要求

(可忽略下面要求描述)

短作业优先调度策略为优化LiteOS的吞吐量。该策略在将线程TCB插入就绪队列时,按照线程执行的时间长短进行排序。运行时间短的线程先运行,运行时间长的线程后运行。该Proj要完成以下内容:

第1步:修改LiteOS内核的PriQueInsert函数,在其中添加相关代码,实现按照任务运行时间的长短将任务的TCB插入就绪队列。

解析:很多同学可能并没有找到PriQueInsert函数,其实是因为韦东山老师在这里下载的是OpenHarmony的1.0版本,这个是2019年的早期版本,至今Openharmony已到4.0版本:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

但是不建议大家下载更高版本,因为可能会面临无法打补丁的问题,最终导致无法编译。所以我们仍旧在OpenHarmony的1.0版本中进行修改,最终实现编译。

下面介绍一下下载高版本OpenHarmony的方法,我在这里下载的是3.2的Release版本:

repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-3.2-Release
repo sync -c -j8

(下载的时间略长,差不多1小时...) 

在新版本中具有PriQueInsert函数,展示在这里:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

第2步:在短作业优先调度策略中,采用LiteOS中定义的SchedParam结构体中的timeSlice成员作为该作业的运行时间。

解析:SchedParam结构体我找了5分钟,发现是在liteos_a/kernel/base/include下的los_sched_pri.h文件夹里。

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

这里补充一下:进入到.h或者.c文件后,可以用快捷键Ctrl+F进行关键词搜索。

需要具备一个意识:可以顺着头文件去进行搜寻,效率较高。

第3步:在用户层生成至少3个线程,通过pthread_attr_getschedparam函数pthread_attr_setschedparam函数,修改所生成线程的调度策略为“短作业优先“调度策略,并对timeSlice进行赋值,表示该线程的运行时间。

解析:pthread_attr_getschedparam函数和pthread_attr_setschedparam函数是属于POSIX线程库提供的函数,没有具体的实现方法,只有定义。

所在的位置是在openharmony/third_party/musl/include下的pthread.h文件里:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

pthread_attr_getschedparam函数:用于获取线程的调度参数,包括线程的优先级等信息。

pthread_attr_setschedparam函数:用于设置线程的调度参数,包括线程的优先级等信息。

这里补充一下:大家可以直接在Files文件夹的根目录里,按下快捷键Ctrl+F,然后输入pthread.h直接搜索到这个文件:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

第4步:验证你所编写的调度策略是正确的。线程内部可以用while语句循环timeSlice规定的时间,然后打印自己的TID后退出。例如,对这3个线程的timeSlice分别赋予1、5、9。那么这3个线程也按照这个顺序完成,即第一个线程1秒后退出,第二个线程5秒后退出,第三个线程9秒后退出。

用户层采用pthread库实现,相关代码参考下面博客:

Linux线程调度策略以及优先级实验(图文)

二、实验过程

修改步骤:

第1步:修改优先级队列函数OsPriQueueEnqueue,在openharmony/kernel/liteos_a/kernel/base/sched/sched_sq/los_priqueue.c中。

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

代码大致实现思路是:通过比较thisTime和frontTime的大小,来安排链表结点的顺序,时间短的排在前面,时间长的排在后面;排在前面的结点先执行,排在后面的后执行,从而实现“短作业优先”。

代码如下,可直接复制粘贴:

VOID OsPriQueueEnqueue(LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority)
{
   if (LOS_ListEmpty(&priQueueList[priority])) {
        *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority;
        LOS_ListTailInsert(&priQueueList[priority], priqueueItem);
    }else{
    	LOS_DL_LIST *currentItem = priQueueList[priority].pstNext;
    	LOS_DL_LIST *prevItem = &priQueueList[priority];
    	while(currentItem != &priQueueList[priority]){
    		UINT32 thisTime = *(UINT32*)(priqueueItem + 1);
    		UINT32 frontTime = *(UINT32*)(currentItem + 1);
    		if(thisTime < frontTime){
    			priqueueItem->pstNext = currentItem;
    			prevItem->pstNext = priqueueItem;
    			if(prevItem->pstPrev){
    				priqueueItem->pstPrev = prevItem;
			}
			if(currentItem->pstPrev){
				currentItem->pstPrev = priqueueItem;
			}
			return;
			}
			prevItem = currentItem;
			currentItem = currentItem->pstNext;
		}
		prevItem->pstNext = priqueueItem;
		priqueueItem->pstNext = &priQueueList[priority];
		priqueueItem->pstPrev = prevItem;
	}
}

第2步:修改LosTaskCB结构体,在openharmony/kernel/liteos_a/kern

el/base/include/los_task_pri.h中。
在pendList下(注意一定要在pendList下添加)添加一条 UINT32          RunTime; 
鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

第3步:修改TSK_INIT_PARAM_S结构体,在openharmony/kernel/liteos_a/kernel/include/los_task.h中。

在policy下添加一条UINT32          RunTime;

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

第4步:修改任务赋值(初始化)函数,在openharmony/kernel/liteos_a/kernel/base/core/los_task. c中。

在taskCB->RunTime下添加一条:taskCB->RunTime      = initParam->RunTime;

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

第5步:编写验证测试程序

借用Project1旭哥的系统调用函数:在openharmony/kernel/liteos_a/syscall下hx_syscall.c函数里。

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程 鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

大致解释一下代码:

void HxSyscall(int num)是函数的入口。

然后分别定义了3个任务(见上图的1 2 3),任务的具体参数都是赋值到initParam里,initParam是TSK_INIT_PARAM_S结构体(参考之前的第3步),重要的是initParam.RunTime所赋的值,这就是运行时间。

LOS_TaskCreate()函数就是生成线程的函数(具体实现见第三部分的第1节)。

代码如下,可直接复制粘贴:

#include "los_printf.h"
#include "los_task_pri.h"
#include "los_base_pri.h"
#include "los_priqueue_pri.h"
#include "los_sem_pri.h"
#include "los_event_pri.h"
#include "los_mux_pri.h"
#include "los_hw_pri.h"
#include "los_exc.h"
#include "los_memstat_pri.h"
#include "los_mp.h"
#include "los_spinlock.h"
#include "los_percpu_pri.h"
#include "los_process_pri.h"

#ifdef __cplusplus
#if __cplusplus

#endif
#endif

#include "stdio.h"
#include "los_task_pri.h"

UINT32 FIRST;
UINT32 SECOND;
UINT32 THIRD;

#define PRIOR 1

void PRIOR_FIRST_TASK(VOID)
{
	PRINTK("Task:One , RunTime:15 s\r\n");
	return;
}
void PRIOR_SECOND_TASK(VOID)
{
	PRINTK("Task:Two , RunTime:30 s\r\n");
	return;
}
void PRIOR_THIRD_TASK(VOID)
{
	PRINTK("Task:Three , RunTime:10 s\r\n");
	return;
}

void HxSyscall(int num){
	UINT32 ret;
	TSK_INIT_PARAM_S initParam;
	LOS_TaskLock();
	PRINTK("\nLOS_TaskLock() Success!\r\n\n");

	initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)PRIOR_FIRST_TASK;
	initParam.usTaskPrio = PRIOR;
	initParam.pcName = "PRIOR_FIRST_TASK";
	initParam.uwStackSize = OS_TASK_RESOURCE_STATCI_SIZE;
	initParam.RunTime = 15;
	initParam.uwResved = LOS_TASK_STATUS_DETACHED;
	ret = LOS_TaskCreate(&FIRST,&initParam);
	if(ret != LOS_OK)
	{
	   LOS_TaskUnlock();
	   PRINTK("Failed_1!\r\n");
	   return;
	}
	PRINTK("Init_Task1_Success!\r\n");


	initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)PRIOR_SECOND_TASK;
	initParam.usTaskPrio = PRIOR;
	initParam.pcName = "PRIOR_SECOND_TASK";
	initParam.uwStackSize = OS_TASK_RESOURCE_STATCI_SIZE;
	initParam.RunTime = 30;
	initParam.uwResved = LOS_TASK_STATUS_DETACHED;
	ret = LOS_TaskCreate(&SECOND,&initParam);
	if(ret != LOS_OK)
	{
	   LOS_TaskUnlock();
	   PRINTK("Failed_2!\r\n");
	   return;
	}
	PRINTK("Init_Task2_Success!\r\n");


	initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)PRIOR_THIRD_TASK;
	initParam.usTaskPrio = PRIOR;
	initParam.pcName = "PRIOR_THIRD_TASK";
	initParam.uwStackSize = OS_TASK_RESOURCE_STATCI_SIZE;
	initParam.RunTime = 10;
	initParam.uwResved = LOS_TASK_STATUS_DETACHED;
	ret = LOS_TaskCreate(&THIRD,&initParam);
	if(ret != LOS_OK)
	{
	   LOS_TaskUnlock();
	   PRINTK("Failed_3!\r\n");
	   return;
	}
	PRINTK("Init_Task3_Success!\r\n\n");
	
	LOS_TaskUnlock();
	return;
}

第6步:开发板测试

按照Project1的方式运行,如果你还不会,请我见下面博客。

鸿蒙LiteOs读源码教程+向LiteOS中添加一个系统调用-CSDN博客

实验结果如下,很清晰:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

这种方式较简单,适合基础较薄弱的同学,快的话估计耗时20~30分钟。

【如果有帮助记得点赞👍收藏☀️嗷~】

三、实验原理讲解(待更新)

第1节:任务创建解析

上面第5步的LOS_TaskCreate函数是在下面的文件路径下:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

具体的代码放在下面,重点是OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB,0)这段代码:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

大家可能会问,上面这个函数是如何与OsPriQueueEnqueue函数连接在一起的?

其实连接的过程很曲折,又很巧妙,大致过程如下:LOS_TaskCreate -> OS_TASK_SCHED_QUEUE_ENQUEUE -> OsTaskSchedQueueEnqueue    -> OS_PROCESS_PRI_QUEUE_ENQUEUE -> OsPriQueueEnqueue

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

像OS_TASK_SCHED_QUEUE_ENQUEUE是个宏,对应的是OsTaskSchedQueueEnqueue函数,在OsTaskSchedQueueEnqueue函数里调用了OS_PROCESS_PRI_QUEUE_ENQUEUE宏,这个宏对应的正是OsPriQueueEnqueue。

第2节:OsPriQueueEnqueue的实现

先看一下OsPriQueueEnqueue初始时的实现,其实是一种“先进先出”的优先级队列。

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

注意传入的参数:

priQueueList是一个指向优先级队列数组的指针,每个数组元素都是一个 LOS_DL_LIST 结构,代表一个优先级。

bitMap是一个指向位图的指针,位图用来快速检索非空优先级队列。

priqueueItem是一个指向将要加入队列的项的指针。

priority是一个 UINT32 类型的变量,表示 priqueueItem 将要被插入的优先级。

注意参数类型:UINT32不过多赘述,是一个32位的二进制位串。LOS_DL_LIST是一个双向链表结构体,pstPrev是前驱节点,pstNext是后继节点:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

VOID OsPriQueueEnqueue(LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority){
    LOS_ASSERT(priqueueItem->pstNext == NULL); //是一个断言,确保 priqueueItem 没有已经加入其他链表。指针不是 NULL,说明 priqueueItem已经在链表中
    if (LOS_ListEmpty(&priQueueList[priority])) { //这是一个检查操作,看在 priority 优先级的链表是否为空
        *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority; //如果对应优先级的链表为空,则在位图中设置对应位。将这个最高位设置到位图的相应位置上,表示现在这个优先级不再为空。
    }
    LOS_ListTailInsert(&priQueueList[priority], priqueueItem);//这行代码执行插入操作,将 priqueueItem 插入到对应优先级的链表末尾。说明基于先进先出原则。
}

如果大家还感兴趣可以所调用函数的具体实现:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程

更新后的函数解释如下,感兴趣的同学可以自行阅读:

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略,harmonyos,华为,学习,线程文章来源地址https://www.toymoban.com/news/detail-743194.html

到了这里,关于鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 鸿蒙Hi3861学习十五-Huawei LiteOS-M(Socket客户端)

            在网络编程的时候,不管是客户端还是服务端,都离不开 Socket 。那什么是Socket,这里做个简单介绍。详细的内容,可以参考这篇文章:WIFI学习一(socket介绍)_wifi socket_t_guest的博客-CSDN博客          socket在计算机领域,被翻译为“ 套接字 ”。它是计算机之间进

    2024年02月05日
    浏览(49)
  • OpenHarmonyOs / LiteOs-a 开发环境搭建

    下一篇:OpenHarmonyOs / LiteOs-a 驱动开发 本文介绍了在 Ubuntu 20.04 系统搭建 OpenHarmonyOs / LiteOs-a 开发环境的方法。 开发板用的是润和的ipcamera_hispark_taurus,芯片是HI3516DV300。 包括安装配置 Ubuntu 系统和注册 Gitee 账户。如果两者都准备好了可以略过。 1. 下载 Ubuntu 系统 https://ubuntu

    2024年02月03日
    浏览(38)
  • Proj4:改进LiteOS中物理内存分配算法

    实验目的 掌握LiteOS系统调用的自定义方法 实验环境 Ubantu和IMX6ULL mini 实验内容 (从代码角度详细描述实验的步骤和过程) 原先代码:   修改后的代码:   主要修改了这一块: 原理如下 : 起初对这个代码与它的注释挺疑惑的,best-fit是在我们可以分配的空闲块中找到一个最适合目

    2024年02月05日
    浏览(51)
  • 项目四 改进LiteOS中物理内存分配算法(未完待续)

    目前仅完成tlsf算法的移植,算法修改等待后续完成(OOAD去了) 1、理解TLSF算法,并根据实验要求改进分配算法 1.物理机:windows操作系统      2.VMware虚拟机:ubuntu 18.04.6 3.开发板:imx6ull Mini 实验问题 :LiteOS中的物理内存分配采用了TLSF算法,该算法较好地解决了最坏情况执

    2024年02月03日
    浏览(53)
  • LiteOS qemu realview-pbx-a9 环境搭建与运行

    最近打算移植搭建 一些常见的 RTOS 的 qemu 开发学习环境,当前 RT-Thread、FreeRTOS 已经成功运行 qemu,LiteOS 初步验证可以正常 运行 qemu realview-pbx-a9 ,这里做个记录 首先学习或者研究 RTOS,只是看内核源码,会比较的枯燥,而是要开发板,可能一上来牵涉过多的硬件驱动,造成学

    2024年02月11日
    浏览(46)
  • 创建一个简单鸿蒙app项目

    文章目录 前言 TypeScript 基础类型 创建一个鸿蒙app 总结 一、前言 鸿蒙系统上的开发已经是趋势了,必须紧跟时代的潮流。先简单了解下鸿蒙系统中,我们开发一个app需要用到的语言,那么就是TypeScript。这篇文章主要讲的就是一些基础的语法。最后我会附上一个demo,可以看看

    2024年01月21日
    浏览(42)
  • harmonyOS鸿蒙官网教程-添加弹窗

    在我们日常使用应用的时候,可能会进行一些敏感的操作,比如删除联系人,这时候我们给应用添加弹窗来提示用户是否需要执行该操作,如下图所示: 弹窗是一种模态窗口,通常用来展示用户当前需要的或用户必须关注的信息或操作。在弹出框消失之前,用户无法操作其他

    2024年02月01日
    浏览(48)
  • 初识鸿蒙:从一个简单的页面跳转开始

    写在前面 前段时间,华为突然重磅发布了mate60 pro,这标志着国产芯片的又一重大突破,同时,也给我们国人带来了一次精神上的鼓舞。另外一个关于鸿蒙的消息,据说是从鸿蒙4.0开始,鸿蒙就不再兼容安卓app了,移除了AOSP源码。从某种程度上说,这也算是回应了别人所说的

    2024年01月21日
    浏览(38)
  • 『牛角书』HarmonyOS鸿蒙实战 开发一个简单聊天助手APP

    我是通过b站上面老师的讲解,跟着老师编写了一个简单聊天助手app,简答实用,对于刚开始接触鸿蒙的我们来说很有帮助。 所用软件为DevEco Studio,点击Create HarmonyOS Project,这里选择了第一个空的项目,点击next会跳至下一个页面。 这里是项目的名称,因为是一个demo,就没有

    2024年02月12日
    浏览(47)
  • 拖拽式万能DIY小程序源码系统 5分钟创建一个小程序,操作简单 带完整的部署搭建教程

    随着移动互联网的发展,越来越多的企业开始使用可视化拖拽式小程序系统来开发和管理自己的应用程序。可视化拖拽式小程序系统为企业提供了一种更快捷、更简便的方式来开发和管理应用程序,这种方式能够大大提高企业的工作效率,使企业更加高效地完成任务。 可视化

    2024年02月05日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包