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

FreeRTOS菜鸟入门(十一)·信号量·二值、计数、递归以及互斥信号量的区别·优先级翻转以及继承机制详解

目录

1.  信号量的基本概念

2.  分类

2.1  二值信号量

2.2  计数信号量

2.3  互斥信号量

2.4  递归信号量

3.  应用场景

3.1  二值信号量

3.2  计数信号量

3.3  互斥信号量

3.4  递归信号量

4.  运作机制

4.1  二值信号量

4.2  计数信号量

4.3  互斥信号量

4.4  递归信号量

5.  互斥量优先级继承机制

5.1  优先级翻转

5.2  优先级继承

6.  区别

6.1  二值信号量(Binary Semaphore)

6.2  计数信号量(Counting Semaphore)

6.3  互斥信号量(Mutex)

6.4  递归信号量(Recursive Mutex)


1.  信号量的基本概念

        在了解信号量的概念之前,我们先来回忆一下,当我们在逻辑编程的时候,时候使用过这样一个变量:用于标记某个事件是否发生,或者标志一下某个东西是否正在被使用,如果是被占用了的或者没发生,我们就不对它进行操作。

        那么当我们来到操作系统,信号量的概念就是:信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问,常用于协助一组相互竞争的任务来访问临界资源。在多任务系统中,各任务之间需要同步或互斥实现临界资源的保护,信号量功能可以为用户提供这方面的支持。

        抽象的来讲,信号量是一个非负整数,所有获取它的任务都会将该整数减一(获取它当然是为了使用资源),当该整数值为零时,所有试图获取它的任务都将处于阻塞状态。通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数。其值的含义分两种情况:

  • 0:表示没有积累下来的释放信号量操作,且有可能有在此信号量上阻塞的任务。
  • 正值,表示有一个或多个释放信号量操作。

2.  分类

2.1  二值信号量

        二值信号量是一种特殊的信号量,其内部状态只有两种:被释放(释放状态)或被占用(占用状态)。为什么叫二值信号量呢?因为信号量资源被获取了,信号量值就是 0,信号量资源被释放,信号量值就是 1,把这种只有 0 和 1 两种情况的信号量称之为二值信号量。

        可以将二值信号量看作只有一个消息的队列,因此这个队列只能为空或满(因此称为二
值),我们在运用的时候只需要知道队列中是否有消息即可,而无需关注消息是什么。

        二值信号量既可以用于临界资源访问,也可用于同步功能。

        而他如何实现任务键的同步呢?举个例子,假设现在又几个任务正在运行,而此时我们想要将任务一和任务二进行同步,那么我们首先创建信号量,在创建后应被置为空,任务 1 获取信号量而进入阻塞,任务 2 在某种条件发生后,释放信号量,于是任务 1 获得信号量得以进入就绪态,如果任务 1 的优先级是最高的,那么就会立即切换任务,从而达到了两个任务间的同步。同样的,在中断服务函数中释放信号量,任务 1 也会得到信号量,从而达到任务与中断间的同步。

2.2  计数信号量

        二值信号量可以被认为是长度为 1 的队列,而计数信号量则可以被认为长度大于 1的队列,信号量使用者依然不必关心存储在队列中的消息,只需关心队列是否有消息即可。

        计数信号量顾名思义,就是计数的,在实际的使用中,我们常将计数信号量用于事件计数与资源管理。

  • 每当某个事件发生时,任务或者中断将释放一个信号量(信号量计数值加 1);
  • 当处理被事件时(一般在任务中处理),处理任务会取走该信号量(信号量计数值减 1)。

        信号量的计数值则表示还有多少个事件没被处理。

        此外,系统还有很多资源,我们也可以使用计数信号量进行资源管理,信号量的计数值表示系统中可用的资源数目,任务必须先获取到信号量才能获取资源访问权,当信号量的计数值为零时表示系统没有可用的资源,但是要注意,在使用完资源的时候必须归还信号量,否则当计数值为 0的时候任务就无法访问该资源了。

2.3  互斥信号量

        互斥信号量其实是特殊的二值信号量,由于其特有的优先级继承机制从而使它更适用于简单互锁,也就是保护临界资源。

        用作互斥时,信号量创建后可用信号量个数应该是满的,任务在需要使用临界资源时,(临界资源是指任何时刻只能被一个任务访问的资源),先获取互斥信号量,使其变空,这样其他任务需要使用临界资源时就会因为无法获取信号量而进入阻塞,从而保证了临界资源的安全。

2.4  递归信号量

        递归嘛,就是可以重复获取调用的,正常信号量是用一个少一个,但是递归不然,用户可以对已经获取的递归信号量进行再次获取该信号量,拥有信号量的所有权,不过成功获取几次就要返回几次。

3.  应用场景

3.1  二值信号量

        首先是在中断当中使用,前面我们也说了,二值信号量非0即1,其裸机的案例,例如我们串口读取传感器数据,当我们串口接收完数据后,不知道下一次什么时候数据发送过来,这些接收的数据也需要进行后续的处理,我们通常会创建一个标志位,当这个标志位为1时表示串口接收到数据,我们根据标志位在外面进行数据处理,处理完后将标志位置0,后面如果一直没有数据进来,标志位一直为0,是不是就类似进入阻塞态,当标志位为1才能运行。

        引申到FreeRTOS中,在串口接收中,我们不知道啥时候有数据发送过来,有一个任务是做接收这些数据处理,总不能在任务中每时每刻都在任务查询有没有数据到来,那样会浪费 CPU 资源,所以在这种情况下我们使用二值信号量,当没有数据到来的时候,任务就进入阻塞态,不参与任务的调度,等到数据到来了,释放一个二值信号量,任务就立即从阻塞态中解除,进入就绪态,然后运行的时候处理数据,这样子系统的资源就会很好的被利用起来。


        前面说了在中断当中的运用,下面我们来举一个任务和任务之间同步的例子,例如:

        假设我们有一个温湿度的传感器,假设是 1s 采集一次数据,那么我们让他在液晶屏中显示数据出来,这个周期也是要 1s 一次的,如果液晶屏刷新的周期是 100ms 更新一次,那么此时的温湿度的数据还没更新,液晶屏根本无需刷新,只需要在 1s 后温湿度数据更新的时候刷新即可,否则 CPU 就是白白做了多次的无效数据更新,CPU的资源就被刷新数据这个任务占用了大半,造成 CPU 资源浪费,如果液晶屏刷新的周期是 10s更新一次,那么温湿度的数据都变化了 10 次,液晶屏才来更新数据,那拿这个产品有啥用,根本就是不准确的,所以,还是需要同步协调工作,在温湿度采集完毕之后,进行液晶屏数据的刷新,这样子,才是最准确的,并且不会浪费 CPU的资源。

3.2  计数信号量

        这个有点类似:生产者-消费者模型。

        比如有一个停车场,里面只有 100 个车位,那么能停的车只有 100 辆,也相当于我们的信号量有 100 个,假如一开始停车场的车位还有 100 个,那么每进去一辆车就要消耗一个停车位,车位的数量就要减一,对应的,我们的信号量在使用之后也需要减一,当停车场停满了 100 辆车的时候,此时的停车位为 0,再来的车就不能停进去了,否则将造成事故,也相当于我们的信号量为 0,后面的任务对这个停车场资源的访问也无法进行,当有车从停车场离开的时候,车位又空余出来了,那么,后面的车就能停进去了,我们信号量的操作也是一样的,当我们释放了这个资源,后面的任务才能对这个资源进行访问。

3.3  互斥信号量

        互斥量又称互斥信号量(本质是信号量),是一种特殊的二值信号量。相较于二值信号量,互斥量更多用于保护资源的互锁。

        其相较于二值信号量的区别在于,互斥量具有“所有权”概念,只有获取(Take)Mutex 的任务才能释放(Give)它,防止其他任务误释放锁。而二值信号量无所有权,任何任务或中断均可调用 xSemaphoreGive(),即使未先调用 Take。

        除此之外,互斥量能够进行优先级翻转,而二值信号量没有此功能(优先级翻转机制将会在下面进行描述)。

3.4  递归信号量

        任务需要递归删除SD卡中的目录及其子目录,涉及多层嵌套的文件系统API调用。

        又或者任务执行一个复杂状态机,其中某些状态的处理函数需要调用其他状态函数,且所有操作需保护共享数据。

4.  运作机制

4.1  二值信号量

        创建信号量时,系统会为创建的信号量对象分配内存,并把可用信号量初始化为用户自定义的个数,二值信号量的最大可用信号量个数为 1。

        二值信号量获取,任何任务都可以从创建的二值信号量资源中获取一个二值信号量,获取成功则返回正确,否则任务会根据用户指定的阻塞超时时间来等待其它任务/中断释放信号量。在等待这段时间,系统将任务变成阻塞态,任务将被挂到该信号量的阻塞等待列表中。

        在二值信号量无效的时候,假如此时有任务获取该信号量的话,那么任务将进入阻塞状态:

        假如某个时间中断/任务释放了信号量,那么,由于获取无效信号量而进入阻塞态的任务将获得信号量并且恢复为就绪态:

        二值信号量运作机制:

4.2  计数信号量

        计数信号量可以用于资源管理,允许多个任务获取信号量访问共享资源,但会限制任务的最大数目。访问的任务数达到可支持的最大数目时,会阻塞其他试图获取该信号量的任务,直到有任务释放了信号量。这就是计数型信号量的运作机制,虽然计数信号量允许多个任务访问同一个资源,但是也有限定,比如某个资源限定只能有 3 个任务访问,那么第 4 个任务访问的时候,会因为获取不到信号量而进入阻塞,等到有任务(比如任务 1)释放掉该资源的时候,第 4 个任务才能获取到信号量从而进行资源的访问,其运作的机制:

4.3  互斥信号量

        用互斥量处理不同任务对临界资源的同步访问时,任务想要获得互斥量才能进行资源访问,如果一旦有任务成功获得了互斥量,则互斥量立即变为闭锁状态,此时其他任务会因为获取不到互斥量而不能访问这个资源,任务会根据用户自定义的等待时间进行等待,直到互斥量被持有的任务释放后,其他任务才能获取互斥量从而得以访问该临界资源,此时互斥量再次上锁,如此一来就可以确保每个时刻只有一个任务正在访问这个临界资源,保证了临界资源操作的安全性:

①:因为互斥量具有优先级继承机制,一般选择使用互斥量对资源进行保护,如果资源被占用的时候,无论是什么优先级的任务想要使用该资源都会被阻塞。

②:假如正在使用该资源的任务 1 比阻塞中的任务 2 的优先级还低,那么任务 1 将被系统临时提升到与高优先级任务 2 相等的优先级(任务 1 的优先级从 L 变成 H)。

③:当任务 1 使用完资源之后,释放互斥量,此时任务 1 的优先级会从 H 变回原来的 L。

④⑤:任务 2 此时可以获得互斥量,然后进行资源的访问,当任务 2 访问了资源的时候,该互斥量的状态又为闭锁状态,其他任务无法获取互斥量。

4.4  递归信号量

        递归信号量是专为嵌套锁需求设计的同步机制,其核心在于允许同一任务多次获取锁,并通过内部计数器管理锁状态。

任务A(高优先级)
│
├─ 获取递归锁(TakeRecursive)       → [锁计数器=1, 持有者=任务A]
│  ├─ 进入临界区
│  ├─ 调用嵌套函数
│  │   ├─ 再次获取递归锁(TakeRecursive) → [锁计数器=2, 持有者=任务A]
│  │   ├─ 操作共享资源
│  │   └─ 释放递归锁(GiveRecursive)    → [锁计数器=1]
│  └─ 释放递归锁(GiveRecursive)        → [锁计数器=0, 锁释放]
│
└─ 其他任务可竞争锁任务B(低优先级)───────────────────┐│
(任务A持有锁期间,任务B尝试获取锁)→ 阻塞等待

图示案例解析
任务A(高优先级)首次获取递归锁:成为持有者,计数器=1。
任务A在临界区内调用嵌套函数,再次获取锁:计数器增至2,仍由任务A持有。
任务B(低优先级)尝试获取锁:因锁被任务A持有,任务B阻塞。
任务A逐层释放锁:每次GiveRecursive减少计数器,直到0时完全释放锁。
任务B被唤醒:锁可用后,任务B获取锁(若其优先级最高)。

5.  互斥量优先级继承机制

        在 FreeRTOS 操作系统中为了降低优先级翻转问题利用了优先级继承算法。优先级继承算法是指,暂时提高某个占有某种资源的低优先级任务的优先级,使之与在所有等待该资源的任务中优先级最高那个任务的优先级相等,而当这个低优先级任务执行完毕释放该资源时,优先级重新回到初始设定值。因此,继承优先级的任务避免了系统资源被任何中间优先级的任务抢占。

        互斥量与二值信号量最大的不同是:互斥量具有优先级继承机制,而信号量没有。也就是说,某个临界资源受到一个互斥量保护,如果这个资源正在被一个低优先级任务使用,那么此时的互斥量是闭锁状态,也代表了没有任务能申请到这个互斥量,如果此时一个高优先级任务想要对这个资源进行访问,去申请这个互斥量,那么高优先级任务会因为申请不到互斥量而进入阻塞态,那么系统会将现在持有该互斥量的任务的优先级临时提升到与高优先级任务的优先级相同,这个优先级提升的过程叫做优先级继承。这个优先级继承机制确保高优先级任务进入阻塞状态的时间尽可能短,以及将已经出现的“优先级翻转”危害降低到最小。

5.1  优先级翻转

        我们知道任务的优先级在创建的时候就已经是设置好的,高优先级的任务可以打断低优先级的任务,抢占 CPU 的使用权。但是在很多场合中,某些资源只有一个,当低优先级任务正在占用该资源的时候,即便高优先级任务也只能乖乖的等待低优先级任务使用完该资源后释放资源。这里高优先级任务无法运行而低优先级任务可以运行的现象称为“优先级翻转”。

        没理解的话,我们附张图对图进行理解,下面是优先级翻转的图解:

① L 任务正在使用某临界资源, H 任务被唤醒,执行 H 任务。但 L 任务并未执行完毕,此时临界资源还未释放。

② 这个时刻 H 任务也要对该临界资源进行访问,但 L 任务还未释放资源, 由于保护机制,H 任务进入阻塞态,L任务得以继续运行,此时已经发生了优先级翻转现象。

③ 某个时刻 M 任务被唤醒,由于 M 任务的优先级高于 L 任务, M 任务抢占了 CPU 的使用权,M任务开始运行,此时 L 任务尚未执行完,临界资源还没被释放。

④ M 任务运行结束,归还 CPU 使用权,L 任务继续运行。

⑤ L 任务运行结束,释放临界资源,H 任务得以对资源进行访问,H 任务开始运行。      

        以上流程可以看出,由于保护机制,高优先级的任务 H 想要访问和 L 相同的临界资源,但是 L 未释放,H 就需要等 L 释放,但是若是此时比 L 更高的优先级的任务发生抢占,占用CPU资源,那么作为最高优先级的任务 H 就需要等待,比自己优先级低,但是比 L 优先级高的任务先执行,等这些任务执行完,才会执行任务 L,等任务 L 运行结束释放完临界资源,此时 H 才会开始运行,这样若是比 L 优先级高的任务过多,那么,到执行 H 任务的时间会被延长,这样就会出现,一种现象最高优先级的 H ,需要一直等待比自己低的任务先执行。在这过程中,H 任务的等待时间过长,这对系统来说这是很致命的,所以这种情况不允许出现,而互斥量就是用来降低优先级翻转的产生的危害。

5.2  优先级继承

        在 H 任务申请该资源的时候,由于申请不到资源会进入阻塞态,那么系统就会把当前正在使用资源的 L 任务的优先级临时提高到与 H 任务优先级相同,此时 M 任务被唤醒了,因为它的优先级比 H 任务低,所以无法打断 L 任务,因为此时 L 任务的优先级被临时提升到 H,所以当 L 任务使用完该资源了,进行释放,那么此时 H 任务优先级最高,将接着抢占 CPU 的使用权, H 任务的阻塞时间仅仅是 L 任务的执行时间,此时的优先级的危害降到了最低:

① L 任务正在使用某临界资源, H 任务被唤醒,执行 H 任务。但 L 任务并未执行完毕,此时临界资源还未释放。

② 这个时刻 H 任务也要对该临界资源进行访问,但 L 任务还未释放资源, 由于保护机制,H 任务进入阻塞态,此时由于优先级继承机制,将 L 任务的优先级拉倒和 H 任务的优先级一样。

③ 某个时刻 M 任务被唤醒,虽然 M 优先级比最初的 L 任务的优先级高,但是,此时 L 的优先级被拉到和 H 任务的优先级一样,所以 M 处于就绪态。

④ L 任务运行结束,释放临界资源,L 任务的优先级回到最初的状态。

⑤ 此时任务 H 和 M均处于就绪态,但是 H 的优先级比 M 的高,且 L 任务已经运行结束,释放临界资源,因此 H 任务得以对资源进行访问,H 任务开始运行。

⑥ M 任务比 L 任务的优先级高,M 任务执行。

6.  区别

6.1  二值信号量(Binary Semaphore)

特点:

只有0(不可用)和1(可用)两种状态。
无所有权概念:任何任务/中断均可Give,即使未先Take。
初始状态为空:需先Give才能Take。

使用场景:

✅ 任务间事件通知(如按键触发)
✅ 中断与任务同步(如串口接收完成)
❌ 不适用于资源保护(无优先级继承)

6.2  计数信号量(Counting Semaphore)

特点:

计数范围≥0:表示可用资源数量(如空闲缓冲区数)。
无所有权限制:生产者Give,消费者Take。

使用场景:

✅ 资源池管理(如缓冲区块、DMA通道)
✅ 生产者-消费者模型
❌ 不适用于互斥访问

6.3  互斥信号量(Mutex)

特点:

严格互斥访问:同一时间仅一个任务可持有锁。
优先级继承:防止低优先级任务阻塞高优先级任务。
初始状态为可用:创建后可直接Take。

使用场景:

✅ 保护共享资源(全局变量、硬件外设)
✅ 防止数据竞争
❌ 不可递归获取

6.4  递归信号量(Recursive Mutex)

特点:

允许同一任务多次获取锁:内部计数器记录Take次数。
必须匹配释放:Give次数等于Take次数才会真正释放。
无优先级继承:可能引发优先级反转。

使用场景:

✅ 递归函数保护(如文件系统递归删除)
✅ 嵌套调用临界区
❌ 不适用于简单互斥

特性二值信号量计数信号量互斥信号量递归信号量
核心用途事件通知资源池管理共享资源保护嵌套锁保护
初始状态空(0)可设置(N)可用(1)可用(1)
所有权有(仅持有者能释放)有(仅持有者能释放)
优先级继承
递归获取
适用场景中断-任务同步缓冲区管理SPI/I2C外设保护递归文件操作

如何选择?

  • 需要事件通知? → 二值信号量
  • 管理有限资源? → 计数信号量
  • 保护共享数据? → 互斥信号量
  • 处理递归调用? → 递归信号量

FreeRTOS菜鸟入门系列_时光の尘的博客-CSDN博客

相关文章:

FreeRTOS菜鸟入门(十一)·信号量·二值、计数、递归以及互斥信号量的区别·优先级翻转以及继承机制详解

目录 1. 信号量的基本概念 2. 分类 2.1 二值信号量 2.2 计数信号量 2.3 互斥信号量 2.4 递归信号量 3. 应用场景 3.1 二值信号量 3.2 计数信号量 3.3 互斥信号量 3.4 递归信号量 4. 运作机制 4.1 二值信号量 4.2 计数信号量 4.3 互斥信号量 4.4…...

C++ -- 内存管理

C --内存管理 1. C/C内存分布2. C中动态内存管理3. C中动态内存管理4. 面对自定义类型5. operator new和operator delete6. new和delete的实现原理6.1 内置类型6.2 自定义类型 7. 定位new(placement new)7.1 底层机制7.2 本质 1. C/C内存分布 2. C中动态…...

基于muduo库实现高并发服务器

文章目录 一、项目介绍二、HTTP服务器1.概念2.Reactor模型2.1单Reactor单线程:单I/O多路复用业务处理2.2单Reactor多线程:单I/O多路复用线程池(业务处理)2.3多Reactor多线程:多I/O多路复用线程池(业务处理&…...

开源PDF解析工具Marker深度解析

开源PDF解析工具Marker深度解析 检索增强生成(RAG)系统的第一步就是做 pdf 解析,从复杂多样的 pdf 中提取出干净准确的文本内容。现有的最优秀的开源工具有两个:Marker 和 MinerU。因为 Marker 是个人开发者做的,文档…...

Redis的内存淘汰机制

Redis的内存淘汰机制和过期策略是2个完全不同的机制, 过期策略指的是使用那种策略来删除过期键,Redis的内存淘汰机制是指:当Redis的运行内存已经超过设置的最大运行内存时,采用什么策略来删除符合条件的键值对,以此来保…...

我国“东数西算”工程对数据中心布局的长期影响

首席数据官高鹏律师团队 我国“东数西算”工程作为国家级战略,旨在优化全国算力资源配置,推动数字经济发展,其对数据中心布局的长期影响主要体现在以下几个方面: 1. 区域协调与资源优化配置 东部与西部分工明确:东部…...

CPT204 Advanced Obejct-Oriented Programming 高级面向对象编程 Pt.10 二叉搜索树

文章目录 1.二叉树(Binary Trees)1.1 二叉搜索树(Binary Search Tree,简称BST)1.1.1 插入操作1.1.2 搜索操作1.1.3 树的遍历(Tree Traversal)1.1.3.1 前序遍历(Preorder Traversal&a…...

MinIO实现https访问

Windows下实现MinIO的https访问. 首先需要自己解决证书问题, 这里可以是个人证书 也可以是花钱买的证书. 现在使用个人开发者证书举例子。 将证书数据解压到你知道的目录之下 然后直接使用命令启动MinIO start minio.exe server --certs-dir D:\xxxxx\tools\certs …...

查看并升级Docker里面Jenkins的Java17到21版本

随着时间推移,java17将逐渐退出舞台,取而代之的是java21。Jenkins也在逐步升级淘汰java版本,今天教大家升级java版本。 Jenkins问题提示 Java 17 end of life in Jenkins You are running Jenkins on Java 17, support for which will end o…...

【KWDB 创作者计划】KWDB 2.2.0多模融合架构与分布式时序引擎

KWDB介绍 KWDB数据库是由开放原子开源基金会孵化的分布式多模数据库,专为AIoT场景设计,支持时序数据、关系数据和非结构化数据的统一管理。其核心架构采用多模融合引擎,集成列式时序存储、行式关系存储及自适应查询优化器,实现跨模…...

Redis的过期设置和策略

Redis设置过期时间主要有以下几个配置方式 expire key seconds 设置key在多少秒之后过期pexpire key milliseconds 设置key在多少毫秒之后过期expireat key timestamp 设置key在具体某个时间戳(timestamp:时间戳 精确到秒)过期pexpireat key millisecon…...

2.3 向量组

本章主要考查向量组的线性关系、秩与极大无关组、向量空间等核心内容,是线性代数的重要基础模块。以下从四个核心考点展开系统梳理: 考点一:向量组的线性表示 核心问题:如何用一组向量线性表出另一组向量?如何判断线性…...

协议(消息)生成

目录 协议(消息)生成主要做什么? 知识点二 制作功能前的准备工作 ​编辑​编辑 制作消息生成功能 实现效果 ​总结 上一篇中配置的XML文件可见: https://mpbeta.csdn.net/mp_blog/creation/editor/147647176 协议(消息)生成主要做什么? //协议生成 主要是…...

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.5 清洗流程自动化(存储过程/定时任务)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL数据清洗自动化:存储过程与定时任务全攻略4.5 清洗流程自动化:构建智能数据处理管道4.5.1 存储过程:复杂清洗逻辑封装4.5.1.1 …...

Python中有序序列容器的概念及其与可变性的关系

什么是有序序列容器? 有序序列容器是Python中一类重要的数据类型,它们具有以下共同特征: 元素有序排列:元素按照插入顺序存储,可以通过位置(索引)访问 可迭代:可以使用for循环遍历…...

数据结构实验8.1:图的基本操作

文章目录 一,实验目的二,实验内容三,实验要求四,算法分析五,示例代码8-1.cpp源码graph.h源码 六,操作步骤七,运行结果 一,实验目的 1.掌握图的邻接矩阵、邻接表的表示方…...

PostgreSQL 的 pg_current_wal_lsn 函数

PostgreSQL 的 pg_current_wal_lsn 函数 pg_current_wal_lsn 是 PostgreSQL 中用于获取当前预写式日志(WAL)写入位置的关键函数,对于数据库监控、复制管理和恢复操作至关重要。 一 基本说明 语法 pg_current_wal_lsn() RETURNS pg_lsn功能 返回当前的 WAL 写入…...

P6822 [PA 2012 Finals] Tax 题解

题目大意 可恶,我们老师竟然把紫题放到了模拟赛里。 题目传送门 原题中题意说的很清楚了。 思路 转化问题 首先先新建两条边,使原题点到点的问题转化成边到边的问题。 可以连接一条从 0 0 0 到 1 1 1,长度为 0 0 0 的边,设这条边为 0 0 0 号边。 还可以连接一条…...

Python异步编程入门:从同步到异步的思维转变

引言 作为一名开发者,你可能已经习惯了传统的同步编程模式——代码一行接一行地执行,每个操作都等待前一个操作完成。但在I/O密集型应用中,这种模式会导致大量时间浪费在等待上。今天,我们将探讨Python中的异步编程,这…...

【Python】使用`python-dotenv`模块管理环境变量

最近田辛老师在进行与AI有关的开发。 在开发和部署 Python 应用程序时(要么是在某个Python环境,要么是在MaxKB等知识库系统),我常常需要根据不同的环境(如开发环境、测试环境、生产环境)使用不同的配置信息…...

破局者手册 Ⅰ:测试开发核心基础,解锁未来测试密钥!

目录 一、引入背景 二、软件测试基础概念 2.1 软件测试的定义 2.2 软件测试的重要性 2.3 软件测试的原则 三、测试类型 3.1 功能测试 3.2 接口测试 3.2.1 接口测试的概念 3.2.2 接口测试的重要性 3.2.3 接口测试的要点 3.2.4 接口测试代码示例(Python r…...

物联网mqtt和互联网http协议区别

MQTT和HTTP是两种不同的网络协议,它们在以下方面存在区别: 一、连接方式 1.MQTT:基于TCP/IP协议,采用长连接方式。客户端与服务器建立连接后,会保持连接状态,可随时进行数据传输,适用于实时性…...

C++笔记之反射、Qt中的反射系统、虚幻引擎中的反射系统

C++笔记之反射、Qt中的反射系统、虚幻引擎中的反射系统 code review! 目录 C++笔记之反射、Qt中的反射系统、虚幻引擎中的反射系统 目录1. 反射基础概念 1...

提示词压缩方法总结与开源工具包

论文标题 AN EMPIRICAL STUDY ON PROMPT COMPRESSION FOR LARGE LANGUAGE MODELS 论文地址 https://arxiv.org/pdf/2505.00019 开源地址 https://github.com/3DAgentWorld/Toolkit-for-Prompt-Compression 作者背景 香港科技大学广州校区,华南理工大学&#…...

【AI提示词】AARRR 模型执行者

提示说明 具备完整的产品知识和数据分析能力,擅长通过AARRR模型优化用户生命周期管理,提升企业收入和市场拓展。 提示词 # Role: AARRR 模型执行者## Profile - language: 中文 - description: 具备完整的产品知识和数据分析能力,擅长通过…...

深入理解 Redis 的主从、哨兵与集群架构

目录 前言1 Redis 主从架构1.1 架构概述1.2 优点与应用场景1.3 局限性 2 Redis 哨兵架构2.1 架构概述2.2 高可用能力的实现2.3 局限与注意事项 3 Redis 集群架构3.1 架构概述3.2 高性能与高可用的统一3.3 限制与挑战 4 架构对比与选型建议结语 前言 在构建高性能、高可用的数据…...

基于CBOW模型的词向量训练实战:从原理到PyTorch实现

基于CBOW模型的词向量训练实战:从原理到PyTorch实现 在自然语言处理(NLP)领域,词向量是将单词映射为计算机可处理的数值向量的重要方式。通过词向量,单词之间的语义关系能够以数学形式表达,为后续的文本分…...

【阿里云大模型高级工程师ACP习题集】2.9 大模型应用生产实践(下篇)

练习题 【单选题】在大模型应用备案中,根据《生成式人工智能服务管理暂行办法》,已上架但未完成合规手续的应用应如何处理?( ) A. 继续运营,同时补办手续 B. 下架处理 C. 暂停部分功能,直至完成合规手续 D. 无需处理,等待监管部门通知 【多选题】在应用服务安全的应用部…...

Matlab实现CNN-BiLSTM时间序列预测未来

Matlab实现CNN-BiLSTM时间序列预测未来 目录 Matlab实现CNN-BiLSTM时间序列预测未来效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CNN-BiLSTM时间序列预测未来; 2.运行环境Matlab2023b及以上,data为数据集,单变量时间序…...

互联网大厂Java求职面试:AI大模型与云原生架构设计深度解析

互联网大厂Java求职面试:AI大模型与云原生架构设计深度解析 第一轮提问:AI大模型与系统集成 技术总监(张总):郑薪苦,你之前提到过Spring AI,那你能讲讲在实际项目中如何将大模型集成到系统中&…...

GD32F103C8T6多串口DMA空闲中断通信程序

以下是一个完全符合C99标准的GD32F103C8T6多串口DMA通信完整实现&#xff0c;代码经过Keil MDK验证并包含详细注释&#xff1a; #include "gd32f10x.h" #include <string.h>/* 硬件配置宏 */ #define USART_NUM 2 /* 使用2个串口 */ #define R…...

labelimg快捷键

一、核心标注快捷键 ‌W‌&#xff1a;调出标注十字架&#xff0c;开始绘制矩形框&#xff08;最常用功能&#xff09;‌A/D‌&#xff1a;切换上一张(A)或下一张(D)图片&#xff0c;实现快速导航‌Del‌&#xff1a;删除当前选中的标注框 二、文件操作快捷键 ‌CtrlS‌&…...

【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

开元类双端互动组件部署实战全流程教程(第2部分:控制端协议拆解与机器人逻辑调试)

作者&#xff1a;那个写了个机器人结果自己被踢出房间的开发者 游戏逻辑房间结构参考界面 从这张图我们能看出&#xff0c;该组件按功能结构细分为多个房间&#xff0c;每个房间底注、准入标准不同&#xff0c;对应的控制模块也有层级区分。常规来说&#xff0c;一个“互动房间…...

51单片机入门教程——蜂鸣器播放天空之城

前言 本教程基于B站江协科技课程进行个人学习整理&#xff0c;专为拥有C语言基础的零基础入门51单片机新手设计。既帮助解决因时间差导致的设备迭代调试难题&#xff0c;也助力新手快速掌握51单片机核心知识&#xff0c;实现从C语言理论到单片机实践应用的高效过渡 。 目录 …...

linux 历史记录命令

命令方式 #/bin/bash #cd /tmp saveFile"tmp.log" isok"grep HISTTIMEFORMAT /etc/profile|wc -l" if [ $isok -eq 0 ] thenecho -e "#history time\nHISTFILESIZE4000\nHISTSIZE4000\nHISTTIMEFORMAT%F %T \nexport HISTTIMEFORMAT\n" >>…...

手表关于MPU6050中的功能实现

MPU6050 OV-Watch 中的睡眠和唤醒功能实现 OV-Watch 项目为 MPU6050 传感器实施了复杂的电源管理&#xff0c;以优化电池寿命&#xff0c;同时保持手腕检测和计步功能。以下是对睡眠和唤醒机制的详细分析&#xff1a; 内核休眠/唤醒功能实现 MPU6050 有两个主要功能来控制其…...

Qt中数据结构使用自定义类————附带详细示例

文章目录 C对数据结构使用自定义类1 QMap使用自定义类1.1 使用自定义类做key1.2 使用自定义类做value 2 QSet使用自定义类 参考 C对数据结构使用自定义类 1 QMap使用自定义类 1.1 使用自定义类做key QMap<key,value>中数据存入时会对存入key值的数据进行比较&#xff…...

深入浅出数据库的函数依赖关系

数据库的“恋爱关系”&#xff1a;函数依赖的那些事儿 在数据库的世界里&#xff0c;属性之间也存在“恋爱关系”。有些属性是“灵魂伴侣”&#xff0c;彼此绑定&#xff1b;有些是“单向奔赴”&#xff0c;只能依赖对方&#xff1b;还有些是“三角恋”&#xff0c;通过中间人…...

C语言易混淆知识点详解

C语言中容易混淆的知识点详解 C语言作为一门基础且强大的编程语言&#xff0c;有许多容易混淆的概念和特性。以下是C语言中一些常见易混淆知识点的详细解析&#xff1a; 1. 指针与数组 相似点&#xff1a; c 复制 下载 int arr[10]; int *ptr arr; 都可以使用[]运算符访…...

如何选择合适的光源?

目录 工业相机光源类型全面指南 1. 环形光源及其变体 高角度环形光源 优点 缺点 典型应用场景 低角度环形光源&#xff08;暗场照明&#xff09; 优点 缺点 典型应用场景 2. 条形光源与组合照明系统 技术特点 组合条形光源 优点 缺点 典型应用场景 3. 同轴光源…...

模块方法模式(Module Method Pattern)

&#x1f9e0; 模块方法模式&#xff08;Module Method Pattern&#xff09; 模块方法模式是一种结构型设计模式&#xff0c;它将复杂的操作分解成一系列相对简单、独立且单一职责的模块。每个模块负责完成一种具体的操作&#xff0c;其他模块或系统可以通过调用这些模块的公开…...

OpenCV第6课 图像处理之几何变换(仿射)

1.仿射变换 2. 平移 3 旋转 附录A 二维旋转矩阵 附录B 三维旋转矩阵与轴角表示 1.仿射变换 仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够保持图像的平直性和平行性。 平直性是指图像经过仿射变换后,直线仍然是直线,平行性是指图像在…...

【中间件】brpc_基础_TimerThread

文章目录 TimerThread1 简介2 主要设计点2.1 数据结构&#xff1a;分层时间轮&#xff08;Hierarchical Timing Wheel&#xff09;2.2 线程模型2.3 任务管理 3 关键代码分析3.1 类定义&#xff08;timer_thread.h&#xff09;3.2 时间轮初始化&#xff08;timer_thread.cpp&…...

拷贝多个Excel单元格区域为图片并粘贴到Word

Excel工作表Sheet1中有两个报表&#xff0c;相应单元格区域分别定义名称为Report1和Report2&#xff0c;如下图所示。 现在需要将图片拷贝图片粘贴到新建的Word文档中。 示例代码如下。 Sub Demo()Dim oWordApp As ObjectDim ws As Worksheet: Set ws ThisWorkbook.Sheets(&…...

网络原理(6)—— 应用层之HTTP协议

目录 一. 应用层 二. 重要应用层协议DNS(Domain Name System) 三. HTTP协议 3.1 HTTP抓包工具 3.2 HTTP格式 3.2.1 请求 3.2.2 响应 3.3 HTTP的工作过程 一. 应用层 应用层协议就像是人们之间的交流规则&#xff0c;它帮助不同的计算机程序&#xff08;应用&#xff09…...

Linux55yum源配置、本机yum源备份,本机yum源配置,网络Yum源配置,自建yum源仓库

参考 太晚了 计划先休息了 大概保存...

250505_HTML

HTML 1. HTML5语法与基础标签1.1 HTML5特性1.1.1 空白折叠现象1.1.2 转义字符 1.2 HTML注释1.3 基础标签1.3.1 div标签1.3.2 标题标签1.3.3 段落标签1.3.1.3.1.3.1.3. 1. HTML5语法与基础标签 1.1 HTML5特性 1.1.1 空白折叠现象 1.1.2 转义字符 1.2 HTML注释 1.3 基础标签 1…...

1. 设计哲学:让字面量“活”起来,提升表达力和安全性

C11引入的用户定义字面量&#xff08;User-Defined Literals&#xff0c;简称UDL&#xff09;是语言层面为程序员打开的一扇“自定义表达式”的大门。它允许我们为字面量&#xff08;比如数字、字符、字符串&#xff09;添加自定义后缀&#xff0c;从而让代码更具语义化、更易读…...

【KWDB 创作者计划】基于 ESP32 + KWDB 的智能环境监测系统实战

一开始萌生这个想法&#xff0c;其实是源自我办公桌上的那颗“小胖子”——一块 ESP32 开发板。它陪我度过了不少调试夜&#xff0c;也让我对物联网有了真正的感知。恰逢 KaiwuDB 举办征文活动&#xff0c;我便想着&#xff0c;何不将我日常积攒下来的一些硬件和数据库实战经验…...