当前位置: 首页 > news >正文

(学习日记)2024.03.15:UCOSIII第十七节:任务的挂起和恢复

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2024.03.15

  • 三十一、UCOSIII:任务的挂起和恢复
    • 1、实现任务的挂起和恢复
      • 1. 定义任务的状态
      • 2. 修改任务控制块TCB
      • 3. 编写任务挂起和恢复函数
        • - OSTaskSuspend()函数
        • - OSTaskResume()函数
    • 2、main()函数
    • 3、实验现象

三十一、UCOSIII:任务的挂起和恢复

本章开始,我们让OS的任务支持挂起和恢复的功能,挂起就相当于暂停,暂停后任务从就绪列表中移除, 恢复即重新将任务插入就绪列表。
一个任务挂起多少次就要被恢复多少次才能重新运行。

1、实现任务的挂起和恢复

1. 定义任务的状态

在任务实现挂起和恢复的时候,要根据任务的状态来操作,任务的状态不同,操作也不同。
有关任务状态的宏定义在os.h中实现, 总共有9种状态

/* ---------- 任务的状态 -------*/
#define  OS_TASK_STATE_BIT_DLY               (OS_STATE)(0x01u)/*   /-------- 挂起位          */#define  OS_TASK_STATE_BIT_PEND              (OS_STATE)(0x02u)/*   | /-----  等待位          */#define  OS_TASK_STATE_BIT_SUSPENDED         (OS_STATE)(0x04u)/*   | | /---  延时/超时位      */#define  OS_TASK_STATE_RDY                    (OS_STATE)(  0u)/*   0 0 0  就绪               */
#define  OS_TASK_STATE_DLY                    (OS_STATE)(  1u)/*   0 0 1  延时或者超时        */
#define  OS_TASK_STATE_PEND                   (OS_STATE)(  2u)/*   0 1 0  等待               */
#define  OS_TASK_STATE_PEND_TIMEOUT           (OS_STATE)(  3u)/*   0 1 1  等待+超时*/
#define  OS_TASK_STATE_SUSPENDED              (OS_STATE)(  4u)/*   1 0 0  挂起               */
#define  OS_TASK_STATE_DLY_SUSPENDED          (OS_STATE)(  5u)/*   1 0 1  挂起 + 延时或者超时*/
#define  OS_TASK_STATE_PEND_SUSPENDED         (OS_STATE)(  6u)/*   1 1 0  挂起 + 等待         */
#define  OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED (OS_STATE)(  7u)/*   1 1 1  挂起 + 等待 + 超时*/
#define  OS_TASK_STATE_DEL                    (OS_STATE)(255u)

2. 修改任务控制块TCB

为了实现任务的挂起和恢复,需要先在任务控制中TCB中添加任务的状态TaskState和任务挂起计数器SusPendCtr这两个成员

struct os_tcb {CPU_STK         *StkPtr;CPU_STK_SIZE    StkSize;/* 任务延时周期个数 */OS_TICK         TaskDelayTicks;/* 任务优先级 */OS_PRIO         Prio;/* 就绪列表双向链表的下一个指针 */OS_TCB          *NextPtr;/* 就绪列表双向链表的前一个指针 */OS_TCB          *PrevPtr;/*时基列表相关字段*/OS_TCB          *TickNextPtr;OS_TCB          *TickPrevPtr;OS_TICK_SPOKE   *TickSpokePtr;OS_TICK         TickCtrMatch;OS_TICK         TickRemain;/* 时间片相关字段 */OS_TICK              TimeQuanta;OS_TICK              TimeQuantaCtr;OS_STATE             TaskState;		//(1)#if OS_CFG_TASK_SUSPEND_EN > 0u		//(2)/* 任务挂起函数OSTaskSuspend()计数器 */OS_NESTING_CTR       SuspendCtr;		//(3)
#endif};
  • (1):TaskState用来表示任务的状态,在本章之前,任务出现了两种状态,一是任务刚刚创建好的时候, 处于就绪态,调用阻塞延时函数的时候处于延时态。本章要实现的是任务的挂起态,再往后的章节中还会有等待态,超时态, 删除态等。
  • (2):任务挂起功能是可选的,通过宏OS_CFG_TASK_SUSPEND_EN来控制,该宏在os_cfg.h文件中定义。
  • (3):任务挂起计数器,任务每被挂起一次,SuspendCtr递增一次,一个任务挂起多少次就要被恢复多少次才能重新运行。

3. 编写任务挂起和恢复函数

- OSTaskSuspend()函数
#if OS_CFG_TASK_SUSPEND_EN > 0u
void   OSTaskSuspend (OS_TCB  *p_tcb,OS_ERR  *p_err)
{CPU_SR_ALLOC();#if 0/* 屏蔽开始 */    			//(1)#ifdef OS_SAFETY_CRITICAL/* 安全检查,OS_SAFETY_CRITICAL_EXCEPTION()函数需要用户自行编写 */if (p_err == (OS_ERR *)0){OS_SAFETY_CRITICAL_EXCEPTION();return;}
#endif#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u/* 不能在ISR程序中调用该函数 */if (OSIntNestingCtr > (OS_NESTING_CTR)0){*p_err = OS_ERR_TASK_SUSPEND_ISR;return;}
#endif/* 不能挂起空闲任务 */if (p_tcb == &OSIdleTaskTCB){*p_err = OS_ERR_TASK_SUSPEND_IDLE;return;}#if OS_CFG_ISR_POST_DEFERRED_EN > 0u/* 不能挂起中断处理任务 */if (p_tcb == &OSIntQTaskTCB){*p_err = OS_ERR_TASK_SUSPEND_INT_HANDLER;return;}
#endif#endif/* 屏蔽结束 */  		//(2)CPU_CRITICAL_ENTER();/* 是否挂起自己 */    		//(3)if (p_tcb == (OS_TCB *)0) {p_tcb = OSTCBCurPtr;}if (p_tcb == OSTCBCurPtr) {/* 如果调度器锁住则不能挂起自己 */if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) {CPU_CRITICAL_EXIT();*p_err = OS_ERR_SCHED_LOCKED;return;}}*p_err = OS_ERR_NONE;/* 根据任务的状态来决定挂起的动作 */		//(4)switch (p_tcb->TaskState){case OS_TASK_STATE_RDY:		//(5)OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();p_tcb->TaskState  =  OS_TASK_STATE_SUSPENDED;p_tcb->SuspendCtr = (OS_NESTING_CTR)1;OS_RdyListRemove(p_tcb);OS_CRITICAL_EXIT_NO_SCHED();break;case OS_TASK_STATE_DLY:		//(6)p_tcb->TaskState  = OS_TASK_STATE_DLY_SUSPENDED;p_tcb->SuspendCtr = (OS_NESTING_CTR)1;CPU_CRITICAL_EXIT();break;case OS_TASK_STATE_PEND:		//(7)p_tcb->TaskState  = OS_TASK_STATE_PEND_SUSPENDED;p_tcb->SuspendCtr = (OS_NESTING_CTR)1;CPU_CRITICAL_EXIT();break;case OS_TASK_STATE_PEND_TIMEOUT:		//(8)p_tcb->TaskState  = OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED;p_tcb->SuspendCtr = (OS_NESTING_CTR)1;CPU_CRITICAL_EXIT();break;case OS_TASK_STATE_SUSPENDED:		//(9)case OS_TASK_STATE_DLY_SUSPENDED:case OS_TASK_STATE_PEND_SUSPENDED:case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:p_tcb->SuspendCtr++;CPU_CRITICAL_EXIT();break;default:		//(10)CPU_CRITICAL_EXIT();*p_err = OS_ERR_STATE_INVALID;return;}/* 任务切换 */OSSched();		//(11)
}
#endif
  • (1)和(2):这部分代码是为了程序的健壮性写的代码,即是加了各种判断, 避免用户的误操作。在μC/OS-III中,这段代码随处可见,但为了讲解方便,我们把这部分代码注释掉, 里面涉及的一些宏和函数我们均不实现,只需要了解即可,在后面的讲解中,要是出现这段代码, 我们直接删除掉,删除掉也不会影响核心功能。
  • (3):如果任务挂起的是自己,则判断下调度器是否锁住,如果锁住则退出返回错误码,没有锁则继续往下执行。
  • (4):根据任务的状态来决定挂起操作。
  • (5):任务在就绪状态,则将任务的状态改为挂起态,挂起计数器置1,然后从就绪列表删除。
  • (6):任务在延时状态,则将任务的状态改为延时加挂起态,挂起计数器置1,不用改变TCB的位置,即还是在延时的时基列表。
  • (7):任务在等待状态,则将任务的状态改为等待加挂起态,挂起计数器置1,不用改变TCB的位置,即还是在等待列表等待。 等待列表暂时还没有实现,将会在后面的章节实现。
  • (8):任务在等待加超时态, 则将任务的状态改为等待加超时加挂起态,挂起计数器置1,不用改变TCB的位置,即还在等待和时基这两个列表中。
  • (9):只要有一个是挂起状态,则将挂起计数器加一操作,不用改变TCB的位置。
  • (10):其他状态则无效,退出返回状态无效错误码。
  • (11):任务切换。凡是涉及改变任务状态的地方,都需要进行任务切换。
- OSTaskResume()函数

OSTaskResume()函数用于恢复被挂起的函数,但是不能恢复自己,挂起倒是可以挂起自己

#if OS_CFG_TASK_SUSPEND_EN > 0u
void  OSTaskResume (OS_TCB  *p_tcb,OS_ERR  *p_err)
{CPU_SR_ALLOC();#if 0/* 屏蔽开始 */			//(1)#ifdef OS_SAFETY_CRITICAL/* 安全检查,OS_SAFETY_CRITICAL_EXCEPTION()函数需要用户自行编写 */if (p_err == (OS_ERR *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return;}
#endif#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u/* 不能在ISR程序中调用该函数 */if (OSIntNestingCtr > (OS_NESTING_CTR)0) {*p_err = OS_ERR_TASK_RESUME_ISR;return;}
#endifCPU_CRITICAL_ENTER();
#if OS_CFG_ARG_CHK_EN > 0u/* 不能自己恢复自己 */if ((p_tcb == (OS_TCB *)0) ||(p_tcb == OSTCBCurPtr)) {CPU_CRITICAL_EXIT();*p_err = OS_ERR_TASK_RESUME_SELF;return;}
#endif#endif/* 屏蔽结束 */			//(2)*p_err  = OS_ERR_NONE;/* 根据任务的状态来决定挂起的动作 */switch (p_tcb->TaskState) {			//(3)case OS_TASK_STATE_RDY:			//(4)case OS_TASK_STATE_DLY:case OS_TASK_STATE_PEND:case OS_TASK_STATE_PEND_TIMEOUT:CPU_CRITICAL_EXIT();*p_err = OS_ERR_TASK_NOT_SUSPENDED;break;case OS_TASK_STATE_SUSPENDED:			//(5)OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();p_tcb->SuspendCtr--;if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {p_tcb->TaskState = OS_TASK_STATE_RDY;OS_TaskRdy(p_tcb);}OS_CRITICAL_EXIT_NO_SCHED();break;case OS_TASK_STATE_DLY_SUSPENDED:			//(6)p_tcb->SuspendCtr--;if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {p_tcb->TaskState = OS_TASK_STATE_DLY;}CPU_CRITICAL_EXIT();break;case OS_TASK_STATE_PEND_SUSPENDED:			//(7)p_tcb->SuspendCtr--;if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {p_tcb->TaskState = OS_TASK_STATE_PEND;}CPU_CRITICAL_EXIT();break;case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:			//(8)p_tcb->SuspendCtr--;if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT;}CPU_CRITICAL_EXIT();break;default:			//(9)CPU_CRITICAL_EXIT();*p_err = OS_ERR_STATE_INVALID;return;}/* 任务切换 */OSSched();			//(10)
}
#endif
  • (1)和(2):这部分代码是为了程序的健壮性写的代码,即是加了各种判断,避免用户的误操作。 在μC/OS-III中,这段代码随处可见,但为了讲解方便,我们把这部分代码注释掉,里面涉及的一些宏和函数我们均不实现, 只需要了解即可,在后面的讲解中,要是出现这段代码,我们直接删除掉,删除掉也不会影响核心功能。
  • (3):根据任务的状态来决定恢复操作。
  • (4):只要任务没有被挂起,则退出返回任务没有被挂起的错误码。
  • (5):任务只在挂起态, 则递减挂起计数器SuspendCtr,如果SuspendCtr等于0,则将任务的状态改为就绪态,并让任务就绪。
  • (6):任务在延时加挂起态, 则递减挂起计数器SuspendCtr,如果SuspendCtr等于0,则将任务的状态改为延时态。
  • (7):任务在等待加挂起态, 则递减挂起计数器SuspendCtr,如果SuspendCtr等于0,则将任务的状态改为等待态。
  • (8):任务在等待加超时加挂起态, 则递减挂起计数器SuspendCtr,如果SuspendCtr等于0,则将任务的状态改为等待加超时态
  • (9):其他状态则无效,退出返回状态无效错误码。
  • (10):任务切换。凡是涉及改变任务状态的地方,都需要进行任务切换。

2、main()函数

这里,我们创建任务1、2和3,其中任务的优先级为1,任务2的优先级为2,任务3的优先级为3。
任务1将自身的flag每翻转一次后均将自己挂起, 任务2在经过两个时钟周期后将任务1恢复,任务3每隔一个时钟周期翻转一次。

int main(void)
{OS_ERR err;/* CPU初始化:1、初始化时间戳 */CPU_Init();/* 关闭中断 */CPU_IntDis();/* 配置SysTick 10ms 中断一次 */OS_CPU_SysTickInit (10);/* 初始化相关的全局变量 */OSInit(&err);/* 创建任务 */OSTaskCreate( (OS_TCB       *)&Task1TCB,(OS_TASK_PTR   )Task1,(void         *)0,(OS_PRIO       )1,(CPU_STK      *)&Task1Stk[0],(CPU_STK_SIZE  )TASK1_STK_SIZE,(OS_TICK       )0,(OS_ERR       *)&err );OSTaskCreate( (OS_TCB       *)&Task2TCB,(OS_TASK_PTR   )Task2,(void         *)0,(OS_PRIO       )2,(CPU_STK      *)&Task2Stk[0],(CPU_STK_SIZE  )TASK2_STK_SIZE,(OS_TICK       )0,(OS_ERR       *)&err );OSTaskCreate( (OS_TCB       *)&Task3TCB,(OS_TASK_PTR   )Task3,(void         *)0,(OS_PRIO       )3,(CPU_STK      *)&Task3Stk[0],(CPU_STK_SIZE  )TASK3_STK_SIZE,(OS_TICK       )0,(OS_ERR       *)&err );/* 启动OS,将不再返回 */OSStart(&err);
}void Task1( void *p_arg )
{OS_ERR err;for ( ;; ) {flag1 = 1;OSTaskSuspend(&Task1TCB,&err);flag1 = 0;OSTaskSuspend(&Task1TCB,&err);}
}void Task2( void *p_arg )
{OS_ERR err;for ( ;; ) {flag2 = 1;OSTimeDly(1);//OSTaskResume(&Task1TCB,&err);flag2 = 0;OSTimeDly(1);;OSTaskResume(&Task1TCB,&err);}
}void Task3( void *p_arg )
{for ( ;; ) {flag3 = 1;OSTimeDly(1);flag3 = 0;OSTimeDly(1);}
}

3、实验现象

进入软件调试,单击全速运行按钮就可看到实验波形,具体见图
在这里插入图片描述
可以看到任务2和任务3的波形图是一样的, 任务1的波形周期是任务2的两倍,与代码实现相符。如果想实现其他效果可自行修改代码实现。

其中,任务二与任务三是靠任务阻塞来完成延时的,只与系统时钟相关。
而任务一每次翻转都会将自己挂起,必须靠任务二将自己恢复才能继续运行。

相关文章:

(学习日记)2024.03.15:UCOSIII第十七节:任务的挂起和恢复

写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…...

聚类分析 | Matlab实现基于NNMF+DBO+K-Medoids的数据聚类可视化

聚类分析 | Matlab实现基于NNMFDBOK-Medoids的数据聚类可视化 目录 聚类分析 | Matlab实现基于NNMFDBOK-Medoids的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 NNMFDBOK-Medoids聚类,蜣螂优化算法DBO优化K-Medoids 非负矩阵分解&#xff08…...

Unity类银河恶魔城学习记录11-3 p105 Inventory UI源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_itemSlot.cs using System.Collections; using System.Collections.Gen…...

Vue3 + Vite + ts引入本地图片

Vue3 Vite ts引入本地图片 单张图片导入 单个图片导入,不过多阐述,通过 import 导入需要使用的图片。 import imgName from /assets/img/imgName.png 多张图片导入 new URL() import.meta.url import.meta.url 是一个 ESM 的原生功能&#xff0…...

图斑或者道路如何单独显示名称在图斑上或者道路上

0序: 遇到过多个测绘、工程、林业相关业务的客户,在加载一些图斑数据,线路数据时,希望能够单独的把图斑的名称,显示到图斑上,或者路网上面。 之前多数推荐的办法: 1.shp可以直接在图新地球中…...

docker 修改默认存储位置

一般系统下系统盘可能磁盘空间有限,需要将docker的存储目录改到其他位置 docker info 查看docker的版本 低版本docker在配置json中增加"graph":"/var/lib/docker" 高版本docker在配置json中增加"data-root":"/var/lib/docker&q…...

Springboot+vue的医疗挂号管理系统+数据库+报告+免费远程调试

效果介绍: Springbootvue的医疗挂号管理系统,Javaee项目,springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的医疗挂号管理系统,采用M(model)V(view)C(con…...

【Effective C++】39 明智而审慎地使用private继承

在之前论证过c如何将public 继承视为 is-a 关系。在哪个例子里,class Student 以 public 形式继承class Person, 于是编译器在必要时刻将Students暗自转化为Person.如果此时我们以 private 继承替换 public继承。 class Person {...}; class Student: p…...

2024年卫生巾行业市场分析报告(京东天猫淘宝线上卫生巾品类电商数据查询)

最近,相关部门辟谣了一则“十大致癌卫生巾黑名单”的消息。这个榜单是部分博主AI撰写,为博眼球、蹭热度的结果。此次事件势必会对卫生巾行业产生一定影响,加剧行业竞争。 根据鲸参谋电商数据平台显示,2024年1月至2月线上电商平台…...

MySQL之表的记录操作

前言 存数据不是目的,目的是能够将存起来的数据取出来或者查出来,并且能够对数据进行增删改查操作,本文将详细介绍表中记录的增删改查操作。对记录的操作属于DML数据库操作语言,可以通过SQL实现对数据的操作,包括实现…...

一种动态联动的实现方法

安防领域中的联动规则 有安防领域相关的开发经历的人知道,IPCamera可以配置使能“侦测”功能,并且指定仅针对图像传感器的某个区载进行侦测。除了基本的“移动侦测"外,侦测的功能点还有细化的类别,如人员侦测、车辆侦测、烟…...

kotlin中使用ViewBinding绑定控件

kotlin中使用ViewBinding绑定控件 什么是ViewBinding? View Binding是Android Studio 3.6推出的新特性,主要用于减少findViewById的冗余代码,但内部实现还是通过使用findViewById。通过ViewBinding,可以更轻松地编写可与视图交互…...

知识积累(五):Transformer 家族的学习笔记

文章目录 1. RNN1.1 缺点 2. Transformer2.1 组成2.2 Encoder2.2.1 Input Embedding(嵌入层)2.2.2 位置编码2.2.3 多头注意力2.2.4 Add & Norm 2.3 Decoder2.3.1 概览2.3.2 Masked multi-head attention 2.4 Transformer 模型的训练和推理2.4.1 训练…...

[Java、Android面试]_13_map、set和list的区别

本人今年参加了很多面试,也有幸拿到了一些大厂的offer,整理了众多面试资料,后续还会分享众多面试资料。 整理成了面试系列,由于时间有限,每天整理一点,后续会陆续分享出来,感兴趣的朋友可关注收…...

Linux进程管理:(六)SMP负载均衡

文章说明: Linux内核版本:5.0 架构:ARM64 参考资料及图片来源:《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址: zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. 前置知识 1.1 CPU管理位图 内核…...

计算机专业学生的成长之路:超越课堂的自我提升策略

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…...

财报解读:“高端化”告一段落,华住开始“全球化”?

2023年旅游业快速复苏,全球酒店业直接受益,总体运营指标大放异彩,多数酒店企业都实现了营收上的明显增长,身为国内龙头的华住也不例外。 3月20日晚,华住集团发布2023年四季度及全年财报。整体实现扭亏为盈,…...

Wifi环境下Unity开发iOS应用启动后HTTPS请求未弹出是否允许无线数据使用数据的弹窗

情况说明 笔者项目在首次启动,登录界面点击登录按钮会先HTTPS请求创建帐号,但是在WIFI网络下,请求后一直提示网络连接失败。但是切换到流量包后,则会弹出"无线数据"使用数据的弹窗,选择允许后则可顺利进入。…...

数据结构的概念大合集03(栈)

概念大合集03 1、栈1.1 栈的定义和特点1.2 栈的基础操作1.3 栈的顺序存储1.3.1 顺序栈1.3.2 栈空,栈满,进栈,出栈的基本思想1.3.3 共享栈1.3.3.1 共享栈的4要素 1.4 栈的链式存储1.4.1 链栈的实现1.4.2 链栈的4个要素 1、栈 1.1 栈的定义和特…...

C++ 哈希表

目录 两数之和 面试题 01.02. 判定是否互为字符重排 存在重复元素 存在重复元素 II 字母异位词分组 两数之和 1. 两数之和 思路1:两层for循环 思路2:逐步添加哈希表 思路3:一次填完哈希表 如果一次填完,那么相同元素的值&…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

深度学习水论文:mamba+图像增强

🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...

网页端 js 读取发票里的二维码信息(图片和PDF格式)

起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的&#xff…...