浙江省网站建设公司黄骅广信建设集团网站

news/2025/10/5 6:42:37/文章来源:
浙江省网站建设公司,黄骅广信建设集团网站,社区网站模版,宁波大型网站推广服务1.为什么自己写一个时间片调度呢 a. 网上其实有很多成熟的时间片调度例程, 包括我最开始参加工作也是抄的网上的例程(还记得当时领导问我看明白了它的调度原理吗, 作为一个自学刚参加工作的我来说, 看懂别人的意思真的很难, 当时只能含糊其词的说看得差不多) b. 在我看来网上的…1.为什么自己写一个时间片调度呢 a. 网上其实有很多成熟的时间片调度例程, 包括我最开始参加工作也是抄的网上的例程(还记得当时领导问我看明白了它的调度原理吗, 作为一个自学刚参加工作的我来说, 看懂别人的意思真的很难, 当时只能含糊其词的说看得差不多) b. 在我看来网上的例程是有一些问题的, 计算时间的那个函数放到定时器中递减, 随着任务的增加, 定时器定时越不准确, 违背了中断的快进快出, 不过话说回来时间片本来就是一个不准确的定时. c. 违背了软件的开闭原则, 每次添加任务都需要进去修改那个定义任务调度的数组. d. 时间为0的任务不能添加到调度中. e. 不能删除任务: 比如某个任务我运行了一段时间, 我根本就不会运行了, 这个时候它还是在调度, 只是我们会在内部放置一个标志位, 让它快速切出去.同时也不能在运行过程中添加任务. 2.程序设计思路 1. 先说下如何定时, 通过一个int类型(32bit)来记录1ms时间过去了, 当定时中断产生中断依次将bit0-31置1, 然后在while(1)中检测有没有置1的bit, 如果有就将任务时间递减. 由于只用一个int类型计时, 这也是为什么程序最大只能支持你程序中, 不能死等超过32ms.  2. 任务的删除, 添加, 转移其实都是链表的知识, 掌握好链表就能明白了. 3.程序移植 2.1 移植超级简单, 只需要添加三个文件: os.c, os.h, list.h; 将time_cb放到1ms定时器中断 #include os.h #include string.h#define MAX_SLICE_SUPPORT 0x1F /* 程序运行过程最大允许被阻塞时间, 如果大于32ms, 将会导致计时不准 */ volatile static unsigned int millisecond; typedef struct {unsigned int time_que;unsigned char bit_head;unsigned char bit_tail; }bit_time_t;bit_time_t task_time {0};/* 任务等待队列和任务就绪队列 */ struct list_head list_wait LIST_HEAD_INIT(list_wait); struct list_head list_ready LIST_HEAD_INIT(list_ready);void add_task(task_t *task) {if(task-time_slice 0) /* 如果时间片设置为0, 则直接挂到就绪队列 */{list_add(task-next, list_ready);} else /* 否则将任务挂到等待队列 */{list_add(task-next, list_wait);} }void delet_task_onself(task_t *task) {list_del(task-next); }static void move_task(task_t *task, struct list_head* soure_list, struct list_head* dest_list) {if(soure_list list_wait) /* if the task in list_wait, then move to list_ready */{list_del(task-next);list_add(task-next, dest_list);}else{/* task-time_slice is not zero can move to list_wait */if(task-time_slice){list_del(task-next);list_add(task-next, dest_list);}} }/* 放到1ms的定时器中断里面 */ inline void time_cb() { task_time.bit_tail millisecond MAX_SLICE_SUPPORT;task_time.time_que | 1 task_time.bit_tail;millisecond; }void run_task() {task_t *node, temp_node;/* 时间队列里面是否有时间 */if(task_time.time_que (1 task_time.bit_head)){/* 将延时等待队列的时间减一 */list_for_each_entry(node, list_wait, next, task_t){node-slice_count--;if(node-slice_count 0) /* 如果时间减完了, 则将当前任务挂到就绪队列 */{memcpy(temp_node, node, sizeof(task_t));node-slice_count node-time_slice;move_task(node, list_wait, list_ready);node temp_node;} }/* 将当前bit的时间清零, 并让bit_head指向下一个位置 */task_time.time_que ~(1 task_time.bit_head);task_time.bit_head;if(task_time.bit_head MAX_SLICE_SUPPORT){task_time.bit_head 0;}}/* 执行就绪队列中的任务, 并将任务重新挂到等待队列 */list_for_each_entry(node, list_ready, next, task_t){memcpy(temp_node, node, sizeof(task_t));move_task(node, list_ready, list_wait);node-task();node temp_node;} }unsigned int current_time() {return millisecond; } unsigned int time_interval(unsigned int *start_time) {if(*start_time 0){*start_time millisecond;}return (millisecond *start_time) ? (millisecond - *start_time) : (0xFFFFFFFF - *start_time millisecond); }#ifndef LIST_H #define LIST_Hstruct list_head {struct list_head *next, *prev; };//双链表的头初始化,next, prev指向自己 #define LIST_HEAD_INIT(name) { (name), (name) }//通过函数初始化头 static inline void INIT_LIST_HEAD(struct list_head *list) {list-next list;list-prev list; }//添加一个新的结点 static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) {next-prev new;new-next next;new-prev prev;prev-next new; }//头插法 static inline void list_add(struct list_head *new, struct list_head *head) {__list_add(new, head, head-next); }//尾插法 static inline void list_add_tail(struct list_head *new, struct list_head *head) {__list_add(new, head-prev, head); }//删除某个结点 static inline void __list_del(struct list_head *prev, struct list_head *next)//将要删除的结点从链表中释放出来 {next-prev prev;prev-next next; } static inline void list_del(struct list_head *entry) //这个函数才是最后的删除函数 {__list_del(entry-prev, entry-next);entry-next (void *)0;entry-prev (void *)0; }//判断结点是否为空 static inline int list_empty(const struct list_head *head) {return head-next head; }//已知结构体中的某个成员的地址ptr,得到结构体的地址 #define list_entry(ptr, type, member) \((type *)((char *)(ptr)-(unsigned long)(((type *)0)-member)))//遍历链表, pos为链表结点, head为链表头, member为链表中的成员, type为结点类型 #define list_for_each_entry(pos, head, member, type) \for (pos list_entry((head)-next, type, member); \pos-member ! (head); \pos list_entry(pos-member.next, type, member)) #endif #ifndef OS_H #define OS_H #include list.h typedef struct {void (*task)();unsigned short time_slice;unsigned short slice_count;struct list_head next; }task_t; void add_task(task_t *task); void delet_task_onself(task_t *task); void run_task(void);void time_cb(void); unsigned int current_time(void); unsigned int time_interval(unsigned int *start_time);#endif2.2 添加任务和调用 我使用了编译器特性, 自动运行程序, 这样就不需要在main函数开头手动调用函数add_task()了 #include ./UART/uart.h #include ./BaseTime/basetime.h #include os.hstatic void task1(void);static task_t task_1 {.task task1,.time_slice 500,.slice_count 500, };static void task1() {printf(task1\n); }/* 使用编译器特性, 自动运行该程序 */ __attribute__((constructor)) static void task1_add() {add_task(task_1); }void task2(); task_t task_2 {.task task2,.time_slice 387,.slice_count 387, }; void task2() {static int count 0;printf(task2ddasdfasfsafafasdsfsfsfsfsfsew\r\n);if(count 5){delet_task_onself(task_2);} }__attribute__((constructor)) void task2_add() {add_task(task_2); }void task3() {printf(task3\r\n); }task_t task_3 {.task task3,.time_slice 632,.slice_count 632, };__attribute__((constructor)) void task3_add() {add_task(task_3); }int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);bsTime_Init(1004, 80);//1ms中断while(1){run_task();} } 3.注意点 1.为了尽可能的节约内存, 以及程序调用的及时性, 程序运行过程最大可以等待32ms去轮询时间递减. 如果内部有死等大于32ms, 就有会导致任务执行时间不准确. 2.如果想在window验证, 由于list.h在visual studio会报错, 如果想验证需要安装gcc(在windows环境下用vscode配置gcc编译代码_windows vscode gcc-CSDN博客),  贴出keil和gcc源码, 有积分的兄弟可以支持下.也可以不下, 我已经将所有代码贴出来了. https://download.csdn.net/download/qq_38591801/88900090 关于1ms中断如何准确测试: 1. 一定要通过逻辑分析仪直接在中断内部拉高拉低电平. 2. 不要通过USB转TTL模块看打印的时间. 这个只能确定个大概, 这个时间不准(我用的是10块钱的DAP烧录器上的串口, 一点不准, 好像使用专门的那种USB转TTL模块还是很准的. 细心的话你会发现这个DAP上的串口会缓存数据). 4.代码仓库 代码已放到gitee, 功能也会进一步完善, 如果有在使用中遇到bug, 可以在博客这边留言. 时间片框架: 基于时间片的裸机程序框架

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

专业商城网站建设价格低装修设计网页版

题目 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", "tea", "tan", "ate", "nat&qu…

桂林北站地址wordpress 多备份

DB Query Analyzer中的事务管理在DB2中的应用 马根峰 ( 广东联合电子收费股份有限公司, 广州 510300) 摘要 事务控制是数据库应用系统中的关键技术之一,概述了事务控制的概念以及《DB Query Analyzer》中的事务控制,以一个具体的实例,给…

北京免费建站天水市建设银行官方网站

前言 CSS(层叠样式表)是网页设计和开发中不可或缺的一部分。它用于描述网页的视觉表现,使页面不仅实现功能,还能提供吸引人的用户体验。本文将介绍 CSS 的基本概念、语法、选择器及其在提升网页美观性方面的重要性。 什么是 CSS&…

做设计专业的能做网站吗汕头网站建设制作公司

前言: 高可用集群,是指以减少服务中断(如因服务器宕机等引起的服务中断)时间为目的的服务器集群技术。简单的说,集群就是一组计算机,它们作为一个整体向用户提供一组网络资源。这些单个的计算机系统就是集群的节点。 …

电商资讯网站有哪些安仁网络推广

以map[int32]string转化为[]byte为例 背景:算法传给我一个map[int32]string类型的值(map的值本身是json转化成的string),我需要把这个值生成一个文件上传到OSS,但是发现通过url下载下来的文件里面有转义字符。 原因&a…

网站建设工作经历网站范例

一.题目要求 给你一个 二进制 字符串 s ,其中至少包含一个 ‘1’ 。 你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组合生成的 最大二进制奇数 。 以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。 注…

江苏建设招标网站安卓游戏模板下载网站

目录 一、Seata 架构 1.1、Seata 架构重要角色 1.2、部署 TC 服务 1.2.1、前言 1.2.2、下载 seata-server 包,解压 1.2.3、修改配置 1.2.4、在 nacos 中添加配置 1.2.5、创建数据库表 1.2.6、启动 TC 服务 1.3、微服务集成 Seata 1.3.1、引入依赖 1.3.2、…

文网站建设常见的推广平台有哪些

1、整个项目预期的任务量 (任务量 所有工作的预期时间)和 目前已经花的时间 (所有记录的 ‘已经花费的时间’),还剩余的时间(所有工作的 ‘剩余时间’) ; 所有工作的预期时间&#…

社区网站如何做内容运营wordpress 4.9.4 汉化

在正常情况下,sed将待处理的行读入模式空间,脚本中的命令就一条接着一条的对该行进行处理,直到脚本执行完毕,然后该行被输出,模式空间请空;然后重复刚才的动作,文件中的新的一行被读入&#xff…

运营实力 网站建设上海闵行做网站的公司

文章目录 一、相关知识1.什么是arp(地址解析协议)2.什么是免费arp(1)简介(2)主要应用(3)代码 3.什么是arp缓存中毒(1)简介(2)过程&…

长春模板建站系统个人静态网站

项目编号: S 045 ,文末获取源码。 \color{red}{项目编号:S045,文末获取源码。} 项目编号:S045,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询社区4…

如何设网站主页北京品牌网站建设

固态硬盘(SSD)因其相对于传统硬盘驱动器(HDD)的诸多优势而日益受到青睐,包括更快的速度、更小的体积、更高的能效以及由于没有活动部件而增强的耐用性。此外,SSD 现在提供更大的存储容量,且价格…

月球尘埃电解技术实现资源就地利用

某机构开发的熔融风化层电解系统可将月球尘埃转化为太阳能电池、氧气和建筑材料,通过电流分离金属与氧气实现资源就地利用,该系统已完成关键设计评审并将于2026年进行自主演示。熔融风化层电解技术让月球尘埃变废为宝…

漏洞赏金计划公开后的三个阶段与应对策略

本文详细分析了漏洞赏金计划公开后通常会经历的三个阶段:提交量激增期、稳定期和长期参与期,并提供了每个阶段的具体特征和管理建议,帮助企业更好地规划和运营自己的漏洞赏金计划。漏洞赏金计划公开后可以期待什么?…

做网站建设业务员怎么样网站服务器主机配置

你是不是做实验经常性的需要一些气象数据,例如PM2.5、相对湿度、月均温度等等…… 但是当你开始寻找数据时就遇到困难了,由于权限、数据网站之类的麻烦你会花费大量无用时间,甚至有时候一无所获得不偿失,这就很头疼了!…

网站项目建设策划书济南建设网站制作优化分析

然后我们来看如何用urllib发送post请求,这里我们 用百度翻译为例 我们翻译一个spider,然后我们看请求,可以看到有很多 找到sug这个 可以看到这里的form data,就是post请求体中的内容 然后我们点击preview其实就是 返回的实际内容 然后请求方式用的post 然后我们把上面的信息…

霸县网站建设山东网站营销seo电话

记得有一次处理Excel文件对比,自己前后使用VBA和NPOI对比了下效率。由于涉及到页面的渲染和刷新,二者的处理速度差了个数量级(10多秒和几十分钟的差别)。当然使用NPOI操作时也做了一定优化。印象这么深刻这次一有需求就想到了NPOI…

网站开发销售怎么做微信分销系统有哪些平台

[html] 编写html时,你有没有用过Emmet插件呢?说说它的优点及规则有哪些? 用过,vscode编辑器自带支持Emmet语法; 它可以帮助快速编写HTML代码,减少复制粘贴的操作; 常见规则: 1. >…

峡山网站建设软件开发和编程的区别

一、问题背景 粉丝在进行 ARM-A 系列软件编程时遇到以下问题,串口打印这段日志后就重启了,粉丝求助问是什么原因? Unhandled Exception in EL3. x30 0x0000000000b99b84 x0 0x00000000179a25b0 x1 …

服务器 多个网站荥阳网站建设公司哪家好

近年来,随着我国工业化、城镇化步伐的不断加快,城市配电网络取得令人瞩目的发展成果。变配电室是供配电系统的核心,在供配电系统中占有特殊的重要地位[1]。变配电室电气设备运行状态和环境信息缺乏必要的监测评估预警手段,如有一日遭遇突发情…