深入理解Linux内核之内核抢占

Linux抢占是如何发生的?_linux cpu抢占特征-CSDN博客


一、内核抢占配置选项

Linux 关于内核抢占配置有三个选项:

CONFIG_PREEMPT_NONE
CONFIG_PREEMPT_VOLUNTARY
CONFIG_PREEMPT



桌面版Linux 配置选项(CONFIG_PREEMPT_VOLUNTARY):

# cat /boot/config-4.19.0-arm64-desktop | grep CONFIG_PREEMPT
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set



服务器Linux 配置选项(CONFIG_PREEMPT_NONE):

# cat /boot/config-4.19.90-24.4.v2101.ky10.aarch64 | grep CONFIG_PREEMPT
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set



嵌入式Linux 配置选项(CONFIG_PREEMPT):

# cat /boot/config-5.15.0-qcomlt-arm64 | grep CONFIG_PREEMPT
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y



对于这三个内核抢占配置选项,桌面Linux选项配置一般都是CONFIG_PREEMPT_VOLUNTARY,服务器Linux配置选项一般都是CONFIG_PREEMPT_NONE,嵌入式Linux配置选项一般都是CONFIG_PREEMPT。

二、使用步骤


2.1 CONFIG_PREEMPT_NONE

PREEMPT_NONE  -- "No Forced Preemption (Server)"

此抢占模型旨在最大化系统的吞吐量。
它遵循传统的Linux内核行为,没有显式的抢占点。
大部分情况下可以提供良好的响应延迟,但无法保证,偶尔可能出现较长的延迟。
适用于服务器或科学/计算系统,更注重原始处理能力而不是调度延迟。



"No Forced Preemption (Server)"选项表示选择传统的Linux抢占模型,该模型注重系统吞吐量(throughput),而不是低延迟的保证。

这是传统的Linux抢占模型,注重系统吞吐量。它旨在通过允许任务在没有中断的情况下执行更长时间,减少抢占开销和上下文切换的次数,从而实现高处理能力和效率。虽然该模型注重吞吐量,但并不提供低延迟的严格保证。大部分时间,延迟仍然可接受,但偶尔可能会出现较长的延迟。如果正在为服务器环境或科学/计算系统配置内核,或者主要目标是最大化内核的原始处理能力,而不考虑调度延迟,那么建议选择此选项。通常更关注整体的处理能力而不是实时响应。

总之,启用"No Forced Preemption (Server)"选项会配置Linux内核以优先考虑吞吐量和原始处理能力,这对于服务器或科学/计算系统是有益的。但是,这可能会导致偶尔出现较长的延迟,并且不提供低延迟的严格保证。

2.2 CONFIG_PREEMPT_VOLUNTARY

PREEMPT_VOLUNTARY -- "Voluntary Kernel Preemption (Desktop)"

此抢占模型旨在通过在内核代码中添加显式的抢占点来降低内核的延迟。
新的抢占点被选择放置以减少重新调度的最大延迟,从而提供更快的应用程序响应。
它允许低优先级进程自愿进行抢占,即使在内核模式下执行系统调用。
通过提供更流畅的应用程序执行,增强系统的响应能力,特别是在负载下。
适用于桌面系统,其中交互事件和用户响应性至关重要。

该选项用于减少内核的延迟,通过在内核代码中添加更多的"显式抢占点"来实现。这些新的抢占点被选择用于减少重新调度的最大延迟,从而提供更快的应用程序响应速度,但会略微降低吞吐量。

该选项通过在内核代码中添加更多的"显式抢占点"来降低内核的延迟。选择这些新的抢占点是为了减少重新调度的最大延迟,提供更快的应用程序响应速度,但会略微降低吞吐量。该模型允许对交互事件进行响应,即使低优先级进程处于内核模式执行系统调用,也可以自愿地进行抢占。这使得应用程序即使在系统负载较重的情况下也能更加流畅地运行。如果正在为桌面系统构建内核,建议选择此选项。

总之,启用"Voluntary Kernel Preemption (Desktop)"选项会在Linux内核中添加更多的显式抢占点,以降低内核的延迟,提供更快的应用程序响应速度。这个模型允许低优先级进程在内核模式下执行系统调用时自愿进行抢占,以使应用程序在系统负载较重时能够更加流畅地运行。该选项适用于构建桌面系统的内核。

内核源码:

// linux-5.4.18/kernel/sched/core.c

#ifndef CONFIG_PREEMPTION
int __sched _cond_resched(void)
{
    if (should_resched(0)) {
        preempt_schedule_common();
        return 1;
    }
    rcu_all_qs();
    return 0;
}
EXPORT_SYMBOL(_cond_resched);
#endif

// linux-5.4.18/include/linux/kernel.h

#ifdef CONFIG_PREEMPT_VOLUNTARY
extern int _cond_resched(void);
# define might_resched() _cond_resched()
#else
# define might_resched() do { } while (0)
#endif



2.3 CONFIG_PREEMPT

PREEMPT --  "Preemptible Kernel (Low-Latency Desktop or Embedded System)"

可抢占内核模型通过使所有非关键区域的内核代码可抢占来进一步降低内核的延迟。
它允许低优先级进程在内核模式下执行系统调用时被强制抢占,即使没有达到自然的抢占点。
此模型改善了整体系统的响应能力,特别适用于具有毫秒级延迟要求的桌面或嵌入式系统。
虽然可能会对内核代码产生轻微开销并稍微降低吞吐量,但在系统负载下提供更流畅的应用程序执行。

该选项用于创建可抢占内核(Preemptible Kernel),旨在降低内核的延迟。

该选项通过使所有非处于关键区域的内核代码可抢占来降低内核的延迟。这允许对交互事件进行响应,即使低优先级进程处于内核模式执行系统调用时也可以被非自愿地抢占,即使它本来不会达到自然抢占点。这使得应用程序即使在系统负载较重的情况下也能更加流畅地运行,但会略微降低吞吐量,并对内核代码产生轻微的运行时开销。如果正在为具有毫秒级延迟要求的桌面或嵌入式系统构建内核,建议选择此选项。

       总之,启用"Preemptible Kernel (Low-Latency Desktop)"选项会创建可抢占的内核,通过使所有非关键区域的内核代码可抢占来降低内核的延迟。这使得低优先级进程在内核模式下执行系统调用时可以被非自愿地抢占,从而使应用程序在系统负载较重的情况下能够更加流畅地运行。该选项适用于具有毫秒级延迟要求的桌面或嵌入式系统。
 

实时内核PREEMPT_RT

config PREEMPT_RT
        bool "Fully Preemptible Kernel (Real-Time)"
        depends on EXPERT && ARCH_SUPPORTS_RT
        select PREEMPTION
        select RT_MUTEXES
        help
          This option turns the kernel into a real-time kernel by replacing
          various locking primitives (spinlocks, rwlocks, etc.) with
          preemptible priority-inheritance aware variants, enforcing
          interrupt threading and introducing mechanisms to break up long
          non-preemptible sections. This makes the kernel, except for very
          low level and critical code paths (entry code, scheduler, low
          level interrupt handling) fully preemptible and brings most
          execution contexts under scheduler control.

          Select this if you are building a kernel for systems which
          require real-time guarantees.

Linux进程调度-应用内核设置调度策略和优先级_sched_setscheduler-CSDN博客

https://wenku.csdn.net/answer/cae236fc06b7185901deca1943b29b20

Linux调度时机(抢占&调度)_linux内核调度时机-CSDN博客

深入理解Linux内核之内核抢占 - 知乎知乎

实验

为了验证开启PREEMPT的效果有准备以下代码:

[root@localhost mod]# cat hard_lock_up_module.c 
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/spinlock.h>
 
MODULE_LICENSE("GPL");
 
static int hog_thread(void *data) {
  static DEFINE_SPINLOCK(lock);
  unsigned long flags;
 
  printk(KERN_INFO "Hogging a CPU now task %s  %d \n",current->comm,smp_processor_id());

  while (1)
    ;

  /* unreached */
  printk(KERN_INFO "Hogging a CPU end %d \n",smp_processor_id());
  return 0;
}
 
static int __init hog_init(void) {
  kthread_run(&hog_thread, NULL, "hog");
  printk(KERN_INFO "hot init task %s %d \n",current->comm,smp_processor_id());
  return 0;
}
 
module_init(hog_init);
MODULE_LICENSE("GPL v2"); 
MODULE_AUTHOR("www");     
MODULE_DESCRIPTION("soft lock up module"); 
MODULE_ALIAS("soft_lock_up_module");       

 上面代码是一个死循环。在没有开启PREEMPT的时候,理论上肯定会产生softlockup。如果开启后,一切正常。只是cpu一直100%。 hog内核线程。此时跑在4号cpu上。然后在taskset -pc 4 1502一直绑定在4号cpu。

[  195.195273] Hogging a CPU now task hog  4


此时再跑一个测试程序:

int main()
{

	while(1)
	{
		printf("test !!!!\n");
	}
	return 0;
}

 gcc 编译为a.out,并taskset  -c 4 ./a.out 绑定在4号cpu。

发现此时各站50%左右。也就是说再开启了抢占的内核上,内核在irq_exit后会进行内核调度。参考:arm64_preempt_schedule_irq

Linux内核有三种内核抢占模型:

  • CONFIG_PREEMPT_NONE:不支持抢占,中断退出后,需要等到低优先级任务主动让出CPU才发生抢占切换;
  • CONFIG_PREEMPT_VOLUNTARY:自愿抢占,代码中增加抢占点,在中断退出后遇到抢占点时进行抢占切换;
  • CONFIG_PREEMPT:抢占,当中断退出后,如果遇到了更高优先级的任务,立即进行任务抢占;

 在开启CONFIG_PREEMPT_VOLUNTARY的时候might_resched才有效,否则是空函数,在调用might_resched->_cond_resched的时候进行进程的主动切换。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

古井无波 2024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值