linux中deadline调度原理与代码注释
简介
deadline调度是比rt调度更高优先级的调度,它没有依赖于优先级的概念,而是给了每个实时任务一定的调度时间,这样的好处是:使多个实时任务场景的时间分配更合理,不让一些实时任务因为优先级低而饿死。deadline调度不是说必须在这个deadline时间点前跑完任务,而是在一个调度周期内,期望在deadline之前调度一次这个任务。理论上这个任务跑的时间是有可能超过deadline时间点,甚至period时间点。
deadline调度策略
三个参数
关于rt调度中优先级是怎么起作用的可以参考之前的一个文章:https://blog.csdn.net/qq_37517281/article/details/134080158
deadline调度用三个额定参数来控制调度,dl_runtime(允许跑的时间) / dl_deadline(期望在一个调度周期内,等待不超过dl_deadline的时间内被调度一次) / dl_period(调度周期)。其中dl_runtime <= dl_deadline <= dl_period。它期望在一个dl_period时长内,任务只能跑dl_runtime的时长,如果没有跑完这个时长,且在同一时间周期内的下次再调度时,只能跑此时到deadline还剩的时间中dl_runtime/dl_deadline的时长;如果下次唤醒已经跳到下一个周期,则可以重新跑dl_runtime的时长;但如果上次跑的时间超过额定的dl_runtime,导致runtime<0,则从下一周期中可跑时长应减去超出的时长(new_runtime = dl_runtime+runtime,其中runtime<0)。一个例外是有太多deadline任务,导致某个不幸的deadline任务长时间没被调度,则下几个周期后,他能跑的时长还是重置为dl_runtime。
一个cpu上的task按deadline先到的顺序,组织为一个红黑树dl_rq->root,其中支持迁移的task还会额外组织成一个红黑树dl_rq->pushable_dl_tasks_root。
一个周期内实际可运行的时长用runtime表示,与dl_runtime都表示时长;但到达的时间点用deadline表示,是一个时间点,与dl_deadline表示一个周期内的时长相区别。
每个cpu运行队列的最早deadline组成了一个大顶堆(顶上的cpu的最早deadline最晚到达),当一个任务需要迁移时,在没有idle cpu的情况下,优先选最早deadline最晚到达的cpu做迁移(find_later_rq)
当一个任务执行了runtime后,会有timer让它不再执行(dl_throttled),它的下一次可重新被调度的时间点为deadline+(dl_period - dl_deadline)。(start_dl_timer)
bandwidth与density
有两个概念不易理解:bandwidth = runtime/period,density = runtime/deadline。
可以简单认为bandwidth是cpu与cpu负载之间的关系,density是一个cpu上任务与任务之间的关系。
bandwidth
bandwidth与utilization(runtime占整个周期的比例)的概念可以等同,每个cpu默认有global_rt_runtime(0.95e+9) / global_rt_period(1e+9) = 0.95 的bandwidth(init_dl_rq_bw_ratio)。当一个cpu的总bandwith(sum(runtime)/period)小时,有可能在运行deadline任务之后,将剩余的dl_period-dl_deadline的时长用于运行一些非deadline的任务(比如低级别的cfs任务,但grub_reclaim函数会尽可能减少这种可能,尽量让deadline任务先做)。
- total_bw:一个cpu调度域中所有cpu的deadline task的bandwidth。其中包含所有从其它调度类提升优先级而来的task。
- bw:(常量)一个cpu调度域的每个cpu的最大bandwidth,等于global_rt_runtime(0.95e+9) / global_rt_period(1e+9)=0.95
- extra_bw:一个cpu运行队列上可分摊到其它域内cpu的空闲bandwidth,最初没有任务时,extra_bw=max_bw。
- this_bw:一个cpu运行队列上active 与非active的task的bandwidth和。
- max_bw:(常量)一个cpu运行队列上的最大bandwidth,等于global_rt_runtime(0.95e+9) / global_rt_period(1e+9)=0.95。
- running_bw:一个cpu运行队列上非inactive任务的bandwidth,它的更新有延迟。wakeup任务时就可add,但任务block 要sub这个bandwidth要等到快到deadline时间点(称为zerolag_time)(更准确的讲是等到deadline前这个时长的时间点:(runtime/dl_runtime)×dl_period)。可以参考下面的图,图中有三种状态:
- active contending:唤醒状态,进入运行队列
- non contending:挂起任务,移出运行队列,但还没有到zerolag_time时间点
- inactive:挂起任务,移出运行队列,且本周期已结束
- 另外还有一个状态 throttled:当一个任务执行runtime后没执行完,要先睡至下个周期开始。或者任务主动yield也是throttled状态。两种情况都要移出运行队列。但其bw依然认为是在队列上且running的。可以认为还在active contending状态。
** +------------------+* wakeup | ACTIVE |* +------------------>+ contending |* | add_running_bw | |* | +----+------+------+* | | ^* | dequeue | |* +--------+-------+ | |* | | t >= 0-lag | | wakeup* | INACTIVE |<---------------+ |* | | sub_running_bw | |* +--------+-------+ | |* ^ | |* | t < 0-lag | |* | | |* | V |* | +----+------+------+* | sub_running_bw | ACTIVE |* +-------------------+ |* inactive timer | non contending |* fired +------------------+*
当向一个调度域中加入一个task时,调度域的total_bw会增加,但要先校验是否overflow,即total_bw + new > bw * total_capacity(total_capacity指域内所有cpu的算力)。然后在每个cpu上均摊减掉extra_bw。
density
density是一个cpu上各deadline任务之间的一个平衡概念,期望每个deadline任务的density都不超过额定的dl_runtime/dl_deadline(CBS rule),当有任务在一个调度周期内,睡眠一定时间又被唤醒时,这个突发的唤醒可能导致它的density过高(因为这个周期的时间已经只剩一部分了,剩余runtime还按完整周期来算,当然会高),需要尝试减少它可执行时长,来平衡与其它任务的关系(Revised CBS rule),即 runtime = (deadline - now) * density。(update_dl_revised_wakeup)
其它名词
dl.overloaded与pushable_queue:overload不是说真的任务忙,而是说这个队列1有可在其它cpu执行的任务a,记在pushable_queue红黑树上。当这个任务a没有在运行时,允许其它队列2与任务a比较deadline的先后,如果比队列2的所有任务deadline都早,就尝试steal这个任务a去执行(特殊情况是,这个任务a比队列2的deadline都早,但任务a又在一些关键区,而被设置了无法迁移(migrate_disable),这时的策略是,给队列1一个信号,让它去检查,是否可以把在运行的任务b迁移出去,从而给这个不能迁移的任务a一个运行机会)。
task生命周期
通用调度过程
调度的大体过程为:
1、选下一个任务(__schedule->pick_next_task):这里会先pull一些其它队列的任务过来(dl_sched_class->balance->pull_dl_task),然后将前一个任务放下(dl_sched_class->put_prev_task),选下一个任务(dl_sched_class->pick_next_task),将它set到队列的next上(pick_next_task>set_next_task),同时注册push的callback(set_next_task->deadline_queue_push_tasks)
2、切换上下文(context_switch->switch_to)
3、切换之后,尝试调push callback将一些可迁移任务给其它cpu队列(finish_task_switch->finish_lock_switch->__balance_callbacks->push_dl_tasks)
deadline任务生命周期
一个任务被选中的开始是第一步中的set_next_task_dl,在这里开启一个计时器至可运行时长runtime结束(start_hrtick_dl),切换运行前,会将任务从迁移队列移出(dequeue_pushable_dl_task),然后运行一段时间后,可预见两种情况(其它情况,比如优先级提升,主要re):
1、runtime用完,高精计时器到达,触发task_tick_dl
2、主要yield让出cpu,触发yield_task_dl
这两种都会调用update_curr_dl更新剩余runtime。如果runtime用完了,队则任务退出运行列,和可迁移队列(__dequeue_task_dl),标记throtled,并启动计时至下个周期开始(start_dl_timer)才重新回到队列。如果runtime没有用完(比如set_next_task_dl->start_hrtick_dl开始计时后,被其它进程抢占,又回到这个进程执行,则runtime没有用完),这时如果它还是最先到deadline的task,则会对剩余的runtime重新调start_hrtick_dl计时。如果是主动sleep的情况,虽然退出队列了,但不会马上将bandwidth去掉,而是开启inactive_task_timer计时,到deadline时间点才将bandwidth去掉(实际是deadline - dl_period*(runtime/dl_runtime)的时间点)(task_non_contending)。
在中断恢复时,触发一次系统的schedule(),它会走pick_next_task的流程,根据deadline是否还是最先到达来决定是否换到其它任务。它可能会选中其它任务,这时将原任务放回可迁移队列(put_prev_task_dl->enqueue_pushable_dl_task)
当throtled到的下一个周期到达时,会将task重新加回运行队列(dl_task_timer->enqueue_task_dl(ENQUEUE_REPLENISH)),并标记resched_curr()来让调度器发现这个任务,重新做抉择。
剩余runtime的扣除
上面提到的更新剩余runtime的方法,在grub(Greedy Reclamation of Unused Bandwidth)算法中不是直接减去运行时长,而是
这个公式在扣除runtime时考虑了总体空闲的情况,将总体的非active的时长(not running 和 extra的时长)分一部分给这个task,让他能再多跑一会(可以看到runtime减去的时间一定小于真实duration),从而减少一个周期内deadline任务都被延迟到下一周期,而本周期中没有deadline任务可跑的情况。(参考的这个pdf:http://retis.santannapisa.it/luca/ospm-summit/2017/Downloads/deadline_reclaiming.pdf,不确定我的理解对不对)
代码注释
enqueue_task_dl
enqueue_task_dl():// 如果task是从其它优先级提升到deadline的// 则不需要throttled到下个周期,因为它只是个临时行为//(比如一个cfs进程1拿了一个锁,而一个deadline进程2在等这个锁,// 则进程1会临时提升为deadline调度级别)if (is_dl_boosted() || !dl_prio(p->normal_prio)) {p->dl.dl_throttled = 0;}// 如果一个task还没有throttled,且超过了deadline,则标记throttled,// 并启动计时期至下个周期才解除throttled(deadline + (dl_period - dl_deadline))// 和重新装填runtime 和 deadline并在deadline前合适的时候调度if (!p->dl.dl_throttled && !dl_is_implicit(&p->dl))dl_check_constrained_dl(&p->dl);enqueue_dl_entity():if (flags & ENQUEUE_WAKEUP) {// 如果是一个从suspend状态激活的任务,且当前时间还没有超过deadline// 由于这个周期的时间已经只剩一部分了,而原来的runtime是按完整周期来算,// 算出的density(=runtime/deadline)会比额定的(dl_runtime/dl_period)要大。// 所以要对可运行时间做修剪:// runtime = (dl_runtime / dl_deadline) * (deadline - now())//// 对于超过deadline,说明这个周期内都没有调度机会// 或已经用完了这个周期的运行时间后睡眠了dl_period-dl_deadline时长// 这时可以直接重置 runtime = dl_runtime, deadline = now + dl_deadlineupdate_dl_entity();} else if (flags & ENQUEUE_REPLENISH) {// 通过优先级提升来的task,或主要释放cpu的task,// 或时间已经超过一个周期的task可以重置runtime 与 deadline// 而因为上个周期执行太久或cpu主频变化导致的执行时间超过可运行时间的场景// runtime是负的,需要在下个周期中将多的可运行时间减掉 (runtime += dl_runtime)replenish_dl_entity(dl_se);} else if (flags & ENQUEUE_RESTORE) {// 因修改task参数(比如修改优先级或可运行的cpu集合)// 导致的dequeue和重新enqueue,强制重置runtime与deadlinesetup_new_dl_entity()}__enqueue_dl_entity():// task 加入 deadline 运行队列rb_add_cached(&dl_se->rb_node, &dl_rq->root, __dl_less);// 更新cpu队列上最早的deadline值// 并更新这个cpu的最早deadline值在整个调度域中的排名//(按从deadline晚到早排序,用堆结构来组织,// 可用于为一个任务选择下个周期在哪个cpu上执行,优选deadline晚的执行)inc_dl_tasks(dl_se, dl_rq);// 如果这个任务支持在其它cpu上跑,则可以被别人拿走执行// 按deadline先后进入pushable排序队列enqueue_pushable_dl_task()
dequeue_task_dl
dequeue_task_dl()// 更新任务的runtime,如果runtime用完,则要throtle(退出队列,并在下个周期开始时回到队列) update_curr_dl();__dequeue_task_dl():// 除去运行队列中的项,更新cpu的最先到达deadline// 和在所有cpu最先到达deadline大顶堆中的位置dequeue_dl_entity();// 从可迁移队列移出,如果没有可迁移task,则清除overload标记dequeue_pushable_dl_task();// 对于 sleep 导致的出队,需要开启计时inactive_timer到deadline的时间点再更新bandwidthtask_non_contending();
update_curr_dl
按grub算法扣除可运行时长,如果没有可运行时长了,则throttle至下个周期
// 在运行一段时间后中断中调用。
update_curr_dl()// 更新执行时间 update_current_exec_runtime();// 扣除时长为 dq = -(max{u, (Umax - Uinact - Uextra)} / Umax) dtdl_se->runtime -= grub_reclaim();// 如果剩余runtime小于0或主动让出cpu,则标记throttled,但这不会改变其bandwidthif (dl_runtime_exceeded(dl_se) || dl_se->dl_yielded) {dl_se->dl_throttled = 1;// 将它移出队列__dequeue_task_dl();// 如果它是其它调度类通过优先级提升而来的任务(这种临时任务不用睡眠等待)// 或dl任务启动计时失败,则再加回来if (unlikely(is_dl_boosted(dl_se) || !start_dl_timer(curr)))enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH);// 大概率它不在运行队列上了,所以,标记重调度if (!is_leftmost(curr, &rq->dl))resched_curr(rq);
pull_dl_task
从其它cpu的可迁移队列拉任务过来。
比如从deadline类型转为其它类型,发现没有deadline任务可以调度了(switched_from_dl)
pull_dl_task():// 遍历每个有可迁移任务的cpufor_each_cpu(cpu, this_rq->rd->dlo_mask) {// 找到比当前cpu的deadline先到的task,从这些task中找到最早到deadline的..// 如果可在本cpu运行,则拿来。deactivate_task(src_rq);set_task_cpu(this_cpu);activate_task(this_rq);// 如果因为一些临时原因不能迁移,则尝试在它所在cpu上换掉正运行的// (前提是正运行的task可迁移,为它找合适的迁移队列)stop_one_cpu_nowait(push_cpu_stop);}
push_dl_tasks
将可迁移任务主动推到其它cpu执行
比如下一个task不能抢占当前task,且下一个可以迁移(task_woken_dl)
这里代码为纯逻辑顺序,没按原代码组织,原代码版本linux v6.6
push_dl_tasks():// 尝试迁移每个pushable task,直到有一个迁移失败。while (push_dl_task(rq)):next_task = pick_next_pushable_dl_task(rq);find_lock_later_rq(next_task):// 为这个任务找合适的队列迁移过去find_later_rq();// 如果找到了下一个队列,则入那个队,并resched_curr那个队列。deactivate_task(rq, next_task, 0);set_task_cpu(next_task, later_rq->cpu);activate_task(later_rq, next_task, 0);resched_curr(later_rq);// 如果没找到下一个队列,且没有新的pushable task加入,则不再尝试if (!dl_task_is_earliest_deadline(task, later_rq)) break;// 如果pushable task变了,则有可能有新task,重试最多三次。..find_later_rq():// 找调度域中idle的cpu中bandwidth能满足这个task的cpu集合// 如果bandwidth都不满足,则找算力最大的cpu// 如果没有 free 的 cpu,则找最早deadline大顶堆中最晚到达deadline的那个cpu,// 确认这个任务的deadline在那个cpu的最早deadline之前,并选中它// 找到的cpu或cpu集合标记为Acpudl_find(&task_rq(task)->rd->cpudl, task, later_mask);// 从原cpu的domain里一层层向上找,与上面备选集合A的交集B// 如果有cpu要求在唤醒过程中考虑亲和性(SD_WAKE_AFFINE标记)则优先考虑for_each_domain(cpu, sd) {// 如果当前cpu在这个B集合中,则用当前cpu是最好的,不做迁移// 否则用round-robin方式在cpu集合B中找一个cpucpumask_any_and_distribute(later_mask, sd);}如果所有备选cpu都没有SD_WAKE_AFFINE标记,则用round-robin方式在备选集合A中找一个cpucpumask_any_distribute(later_mask);
set_next_task_dl
标记即将运行的任务是这个任务
set_next_task_dl():// 将要在本cpu运行的task,不再支持被其它cpu倫过去执行dequeue_pushable_dl_task();// 启动定时到可运行时长runtime耗尽start_hrtick_dl();// 更新load值// 参考:https://blog.csdn.net/qq_37517281/article/details/134039766update_dl_rq_load_avg非deadline调度类,load sum 累加0,load avg 累加1,// 在切换至这个task后,尝试将下一个到deadline的进程迁移到其它cpu执行deadline_queue_push_tasks(push_dl_tasks);
wakeup_preempt_dl
判断是否可抢占当前task
wakeup_preempt_dl():// 两任务deadline不同,选deadline先到的// 两任务deadline相同,原则是尽可能不抢占,可抢占的条件:// 运行中任务可移动且超过了deadline,且要换入的任务不可移动且deadline没到。
put_prev_task_dl
将前一个任务从运行队列移除
put_prev_task_dl():// 扣除运行时长update_curr_dl();// 累积load_sum/avgupdate_dl_rq_load_avg();// 如果任务可在其它cpu执行,则加入可迁移队列,并在下次调度时尝试迁移enqueue_pushable_dl_task();
switched_to_dl
从其它调度类型切至deadline调度
switched_to_dl():// 如果这个任务在一个周期时间内迁走又迁回,则将计时器去掉if (hrtimer_try_to_cancel(&p->dl.inactive_timer) == 1)put_task_struct(p);// 任务不是当前队列的任务if (rq->curr != p) {// 如果它可迁移,加入pushable队列deadline_queue_push_tasks();// 尝试抢当前在跑的taskwakeup_preempt_dl();}// 如果提升优先级变为deadline任务,或用户指定它调度类型变更// 它的cpu没有变,还是之前运行的cpu,需要更新下loadupdate_dl_rq_load_avg();
相关文章:
linux中deadline调度原理与代码注释
简介 deadline调度是比rt调度更高优先级的调度,它没有依赖于优先级的概念,而是给了每个实时任务一定的调度时间,这样的好处是:使多个实时任务场景的时间分配更合理,不让一些实时任务因为优先级低而饿死。deadline调度…...
jquery、vue、uni-app、小程序的页面传参方式
jQuery、Vue、Uni-app 和小程序(例如微信小程序)都有它们自己的页面传参方式。下面分别介绍这几种方式的页面传参方式: jQuery: 在jQuery中,页面传参通常是通过URL的查询参数来实现的。例如: <a href"page2…...
ModuleNotFoundError: No module named ‘openai.error‘
ModuleNotFoundError: No module named ‘openai.error’ result self.fn(*self.args, **self.kwargs) File “H:\chatGPTWeb\chatgpt-on-wechat\channel\chat_channel.py”, line 168, in _handle reply self._generate_reply(context) File “H:\chatGPTWeb\chatgpt-on-wec…...
理解pom.xml中的parent标签
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏&…...
element ui el-avatar 源码解析零基础逐行解析
avatar功能介绍 快捷配置头像的样式 avatar 的参数配置 属性说明参数size尺寸type string 类型 (‘large’,‘medium’,‘small’)number类型 validator 校验shape形状circle (原型) square(方形)icon传入的iconsrc传入的图片st…...
Linux下c语言实现动态库的动态调用
在Linux操作系统下,有时候需要在不重新编译程序的情况下,运行时动态地加载库,这时可以通过Linux操作系统提供的API可以实现,涉及到的API主要有dlopen、dlsym和dlclose。使用时,需要加上头文件#include <dlfcn.h>…...
为什么MCU在ADC采样时IO口有毛刺?
大家在使用MCU内部ADC进行信号采样一个静态电压时,可能在IO口上看到这样的波形。这个时候大家一般会认识是信号源有问题,但仔细观察会发现这个毛刺的频率是和ADC触发频率一样的。 那么为什么MCU在ADC采样时IO口会出现毛刺呢?这个毛刺对结果有…...
C# 将 Word 转化分享为电子期刊
目录 需求 方案分析 相关库引入 关键代码 Word 转 Pdf Pdf 转批量 Jpeg Jpeg 转为电子书 实现效果演示 小结 需求 曾经的一个项目,要求实现制作电子期刊定期发送给企业进行阅读,基本的需求如下: 1、由编辑人员使用 Microsoft Word…...
网络世界的黑暗角落:常见漏洞攻防大揭秘
网络世界的黑暗角落:常见漏洞攻防大揭秘 今天带来了网站常见的漏洞总结,大家在自己的服务器上也需要好好进行防护,密码不要过于简单.不然非常容易遭到攻击,最终达到不可挽回的损失.很多黑客想网络乞丐一样将你服务器打宕机,然后要求你进行付费.不知道大家有没有遇到…...
通信领域发展方向
5G网络技术:随着5G网络的建设和商用推广,各家运营商、厂商和研究机构都在探索5G技术的应用场景和解决方案,如网络切片、毫米波通信、多用户MIMO等。 物联网技术:物联网技术已经成为通信行业的重点发展领域,包括传感器…...
21 3GPP中 5G NR高速列车通信标准化
文章目录 信道模型实验——物理层设计相关元素μ(与子载波间隔有关)设计参考信号(DMRS) 本文提出初始接入、移动性管理、线性小区设计等高层技术。描述3GPP采用HST场景的评估参数,阐释了HST应用的物理层技术,包括数字通信和参考信号设计,链路…...
【网络安全】-Linux操作系统—CentOS安装、配置
文章目录 准备工作下载CentOS创建启动盘确保硬件兼容 安装CentOS启动安装程序分区硬盘网络和主机名设置开始安装完成安装 初次登录和配置更新系统安装额外的软件仓库安装网络工具配置防火墙设置SELinux安装文本编辑器配置SSH服务 总结 CentOS是一个基于Red Hat Enterprise Linu…...
CCNP课程实验-OSPF-CFG
目录 实验条件网络拓朴需求 配置实现基础配置1. 配置所有设备的IP地址 实现目标1. 要求按照下列标准配置一个OSPF网络。 路由协议采用OSPF,进程ID为89 ,RID为loopback0地址。3. R4/R5/R6相连的三个站点链路OSPF网络类型配置成广播型,其中R5路…...
【Spring Security】打造安全无忧的Web应用--入门篇
🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Spring Security的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.Spring Security是什么 1.概…...
【每日一题】【12.20】2828.判别首字母缩略词
🔥博客主页: A_SHOWY🎥系列专栏:力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 1.题目链接 2828. 判别首字母缩略词https://leetcode.cn/problems/check-if-a-string-is-an-acronym-of-words/ 2.题目描述 今天…...
LabVIEW开发振动数据分析系统
LabVIEW开发振动数据分析系统 自动测试系统基于LabVIEW平台设计,采用了多种高级硬件设备。系统的硬件组成包括PCB振动加速度传感器,这是一种集成了传统压电加速度传感器和电荷放大器的先进设备,能够直接与采集仪器连接。此外,系统…...
去掉乘法运算的加法移位神经网络架构
[CVPR 2020] AdderNet: Do We Really Need Multiplications in Deep Learning? 代码:https://github.com/huawei-noah/AdderNet/tree/master 核心贡献 用filter与input feature之间的L1-范数距离作为“卷积层”的输出为了提升模型性能,提出全精度梯度…...
【TB作品】51单片机,具有报时报温功能的电子钟
2.具有报时报温功能的电子钟 一、功能要求: 1.显示室温。 2.具有实时时间显示。 3.具有实时年月日显示和校对功能。 4.具有整点语音播报时间和温度功能。 5.定闹功能,闹钟音乐可选。 6.操作简单、界面友好。 二、设计建议: 1.单片机自选(C51、STM32或其他单片机)。 2.时钟日历芯…...
了解C++工作机制
基于hello.cpp对C的运行进行一个初步认识,并介绍国外C大佬Cherno常用的项目结构和调试Tips C是如何工作的 C工作流程1.实用工程(project)结构(1)Microsoft Visual Studio2022新建项目后,自动生成的原始文件…...
力扣题目学习笔记(OC + Swift) 14. 最长公共前缀
14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 方法一 竖向扫描法 个人感觉纵向扫描方式比较直观,符合人类理解方式,从前往后遍历所有字符串的每一列,比较相同列上的…...
WinSW设置应用程序开机启动
前言 由于使用windows自动的自启方法,不管是将程序启动服务放到开机自启文件夹中,还是创建任务计划程序,都没有很好的实现程序的开机自启效果,而WinSW很好的解决了这个问题。 下载 WinSW下载地址 注意:不同版本&#…...
Leetcode—96.不同的二叉搜索树【中等】
2023每日刷题(六十四) Leetcode—96.不同的二叉搜索树 算法思想 实现代码 class Solution { public:int numTrees(int n) {vector<int> G(n 1, 0);G[0] 1;G[1] 1;for(int i 2; i < n; i) {for(int j 1; j < i; j) {G[i] G[j - 1] * …...
正则表达式零宽断言
正则表达式零宽断言 工具类,正则表达式匹配文本内容正则表达式语法例子例子01零宽断言?< 不包含左边值? 不包含右边值例子 常用正则表达式校验数字的表达式校验字符的表达式 工具类,正则表达式匹配文本内容 /*** 正则表达式工具类*/ public class…...
uni-app学习记录
uni-app注意点记录 跳转到 tabBar 页面只能使用 switchTab 跳转路由API的目标页面必须是在pages.json里注册的vue页面。如果想打开web url,在App平台可以使用 plus.runtime.openURL或web-view组件;H5平台使用 window.open;小程序平台使用web…...
API资源对象StorageClass;Ceph存储;搭建Ceph集群;k8s使用ceph
API资源对象StorageClass;Ceph存储;搭建Ceph集群;k8s使用ceph API资源对象StorageClass SC的主要作用在于,自动创建PV,从而实现PVC按需自动绑定PV。 下面我们通过创建一个基于NFS的SC来演示SC的作用。 要想使用NFS的SC,还需要安装一个NFS…...
Databend 开源周报第 124 期
Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。 新增对 Delta 和…...
Arduino开发实例-液体流量测量
液体流量测量 文章目录 液体流量测量1、流量传感器介绍2、硬件准备及接线3、代码实现在本文中,将介绍如何流量传感器进行测量液体流量。 流量传感器用于测量液体流速。 市场上有不同类型的流量传感器,在本文中,我们将使用霍尔效应流量传感器。 这些类型的流量传感器是非侵入…...
【idea】解决sprintboot项目创建遇到的问题
目录 一、报错Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found 二、报错java: 错误: 无效的源发行版:17 三、java: 无法访问org.springframework.web.bind.annotation.CrossOrigin 四、整合mybatis的时候,报java.lang.Ill…...
ADC芯片CS1237在电子秤方案的优势
随着科技的不断发展,电子秤已经成为我们日常生活中不可或缺的测量工具。为了满足用户对于高精度、高稳定性的需求,芯海ADC芯片CS1237应运而生,为电子秤方案带来了革命性的变革。 一、芯海ADC芯片CS1237介绍 芯海ADC芯片CS1237是一款高性能…...
Leetcode的AC指南 —— 哈希表:202. 快乐数
摘要: Leetcode的AC指南 —— 哈希表:202. 快乐数。题目介绍:编写一个算法来判断一个数 n 是不是快乐数。 文章目录 一、题目二、解析1、哈希表 一、题目 题目介绍:编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为…...
邢台网约车平台有哪些/百度搜索引擎优化公司哪家强
转载:http://www.cnblogs.com/CCGGAAG/p/7800323.html 上篇,我们说了如何配置基础的环境,配置好了python2、wxPython 、robot framework、robot framework-ride,这篇我们来根据已经配置好的环境来简单介绍一下RF(Robot…...
做响应式网站多少钱/优化设计答案六年级上册
打造私家园林 苏州翠园再续园林情结http://www.sina.com.cn 2001年02月21日10:58 解放日报一座460平方米的现代版私家园林———翠园,近日出现在苏州古城西北街木谷巷。园林主人苏州国画院副院长、金石篆刻大师蔡廷辉利用住宅拆迁的机会,费时14个月设计监…...
建设网站用什么app/宁波seo博客
近日在使用SQL Server 2008 Management Studio时遇到一个奇怪的问题,之前的数据库是用SQL Server 2005创建的,我将数据库文件复制到另外一台机器上,这台机器上安装的是SQL Server 2008,将数据库文件附加进来没有任何问题ÿ…...
专业的河南网站建设价格/东莞网络公司电话
http://www.zhdba.com/mysqlops/category/mysql-source-code/...
网站空间更换/常州网络推广平台
本文将简单介绍RSA在webshell中的使用,旨在帮助小白们快速制作自己的流量混淆工具。关于RSA援引百度百科对RSA的介绍:RSA是1977年由罗纳德李维斯特(Ron Rivest)、阿迪萨莫尔(Adi Shamir)和伦纳德阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省…...