内核抢占API

Linux实时扩展(PREEMPT_RT) PREEMPT_RT linux 阅读详情

早期的Linux核心是不可抢占的。它的调度方法是:一个进程可以通过schedule()函数自愿地启动一次调度。非自愿的强制性调度只能发生在 每次从系统调用返回的前夕以及每次从中断或异常处理返回到用户空间的前夕。但是,如果在系统空间发生中断或异常是不会引起调度的。这种方式使内核实现得以 简化。但常存在下面两个问题:

  • 如果这样的中断发生在内核中,本次中断返回是不会引起调度的,而要到最初使CPU从用户空间进入内核空间的那次系统调用或中断(异常)返回时才会发生调度。
  • 另外一个问题是优先级反转。在Linux中,在核心态运行的任何操作都要优先于用户态进程,这就有可能导致优先级反转问题的出现。例如,一个低优先级的用户进程由于执行软/硬中断等原因而导致一个高优先级的任务得不到及时响应。

当前的Linux内核加入了内核抢占(preempt)机制。内核抢占指用户程序在执行系统调用期间可以被抢占,该进程暂时挂起,使新唤醒的高优先 级进程能够运行。这种抢占并非可以在内核中任意位置都能安全进行,比如在临界区中的代码就不能发生抢占。临界区是指同一时间内不可以有超过一个进程在其中 执行的指令序列。在Linux内核中这些部分需要用自旋锁保护。

内核抢占要求内核中所有可能为一个以上进程共享的变量和数据结构就都要通过互斥机制加以保护,或者说都要放在临界区中。在抢占式内核中,认为如果内 核不是在一个中断处理程序中,并且不在被 spinlock等互斥机制保护的临界代码中,就认为可以"安全"地进行进程切换。

Linux内核将临界代码都加了互斥机制进行保护,同时,还在运行时间过长的代码路径上插入调度检查点,打断过长的执行路径,这样,任务可快速切换进程状态,也为内核抢占做好了准备。

Linux内核抢占只有在内核正在执行例外处理程序(通常指系统调用)并且允许内核抢占时,才能进行抢占内核。禁止内核抢占的情况列出如下:

(1)内核执行中断处理例程时不允许内核抢占,中断返回时再执行内核抢占。

(2)当内核执行软中断或tasklet时,禁止内核抢占,软中断返回时再执行内核抢占。

(3)在临界区禁止内核抢占,临界区保护函数通过抢占计数宏控制抢占,计数大于0,表示禁止内核抢占。

抢占式内核实现的原理是在释放自旋锁时或从中断返回时,如果当前执行进程的 need_resched 被标记,则进行抢占式调度。

Linux内核在线程信息结构上增加了成员preempt_count作为内核抢占锁,为0表示可以进行内核高度,它随spinlock和 rwlock等一起加锁和解锁。线程信息结构thread_info列出如下(在include/asm-x86/thread_info.h中):

struct thread_info { struct task_struct *task; struct exec_domain *exec_domain; __u32 flags; __u32 status; __u32 cpu; int preempt_count; mm_segment_t addr_limit; struct restart_block restart_block;#ifdef CONFIG_IA32_EMULATION void __user *sysenter_return; #endif }; #endif

 

内核调度器的入口为preempt_schedule(),他将当前进程标记为TASK_PREEMPTED状态再调用schedule(),在TASK_PREEMPTED状态,schedule()不会将进程从运行队列中删除。

内核抢占API函数

在中断或临界区代码中,线程需要关闭内核抢占,因此,互斥机制(如:自旋锁(spinlock)、RCU等)、中断代码、链表数据遍历等需要关闭内 核抢占,临界代码运行完时,需要开启内核抢占。关闭/开启内核抢占需要使用内核抢占API函数preempt_disable和 preempt_enable。

内核抢占API函数说明如下(在include/linux/preempt.h中):

preempt_enable() //内核抢占计数preempt_count减1

preempt_disable() //内核抢占计数preempt_count加1

preempt_enable_no_resched()  //内核抢占计数preempt_count减1,但不立即抢占式调度

preempt_check_resched () //如果必要进行调度

preempt_count() //返回抢占计数

preempt_schedule() //核抢占时的调度程序的入口点

  内核抢占API函数的实现宏定义列出如下(在include/linux/preempt.h中):

#define preempt_disable() / do { / inc_preempt_count(); / barrier(); / //加内存屏障,阻止gcc编译器对内存进行优化 } while (0) #define inc_preempt_count() / do { / preempt_count()++; / } while (0)#define preempt_count() (current_thread_info()->preempt_count)

内核抢占调度

Linux内核在硬中断或软中断返回时会检查执行抢占调度。分别说明如下:

(1)硬中断返回执行抢占调度

Linux内核在硬中断或出错退出时执行函数retint_kernel,运行抢占函数,函数retint_kernel列出如下(在arch/x86/entry_64.S中):

#ifdef CONFIG_PREEMPT ENTRY(retint_kernel) cmpl $0,threadinfo_preempt_count(%rcx) jnz retint_restore_args bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx) jnc retint_restore_args bt $9,EFLAGS-ARGOFFSET(%rsp) jnc retint_restore_args call preempt_schedule_irq jmp exit_intr #endif

函数preempt_schedule_irq是出中断上下文时内核抢占调度的入口点,该函数被调用和返回时中断应关闭,保护此函数从中断递归调用。该函数列出如下(在kernel/sched.c中):

asmlinkage void __sched preempt_schedule_irq(void) { struct thread_info *ti =current_thread_info();   BUG_ON(ti->preempt_count || !irqs_disabled());   do {add_preempt_count(PREEMPT_ACTIVE); local_irq_enable(); schedule(); local_irq_disable();sub_preempt_count(PREEMPT_ACTIVE);   barrier(); } while(unlikely(test_thread_flag(TIF_NEED_RESCHED))); }

调度函数schedule会检测进程的 preempt_counter 是否很大,避免普通调度时又执行内核抢占调度。

(2)软中断返回执行抢占调度

在打开页出错函数pagefault_enable和软中断底半部开启函数local_bh_enable中,会调用函数 preempt_check_resched检查是否需要执行内核抢占。如果不是并能调度,进程才可执行内核抢占调度。函数 preempt_check_resched列出如下:

#define preempt_check_resched() / do { / if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) / preempt_schedule(); / } while (0)

函数preempt_schedule源代码与函数preempt_schedule_irq基本上一样,对进程进行调度,这里不再分析

[linux][调度] 内核抢占入门 —— 线程调度次数与 CONFIG_PREEMPTION 当打开内核抢占时,也就是定义了 CONFIG_PREEMPTION 这个宏。那么打开这个宏的时候,具体定义了那些内容呢?本人使用的源码版本是 5.10.186。 阅读详情

相关推荐

Linux 网络协议栈之内核锁(二)—— 内核抢占

一、内核抢占     早期的Linux核心是不可抢占的。它的调度方法是:一个进程可以通过schedule()函数自愿地启动一次调度。非自愿的强制性调度只能发生在每次从系统调用返回的前夕以及每次从中断或异常处理返回到用户空间的前夕。但是,如果在系统空间发生中断或异常是不会引起调度的。这种方式使内核实现得以简化。但常存在下面两个问题: 1、如果这样的中断发生在内核中,本次中断返回是不会引起调度的,

知秋一叶 1249

preempt_disable宏

1.相关数据结构及函数如下: struct thread_info中 { unisgned int preempt_count;//线程抢占引用计数器,为0才能被抢占 } 2.preempt_disable的定义 #define preempt_disable() \ do{ \ inc_preempt_count(); \//增加preempt_cou...

hzj_001的博客 2926

Linux: lock: preempt_disable; CONFIG_PREEMPT_COUNT;CONFIG_PREEMPT

摘要:本文分析了Linux内核中的preempt_disable()函数,指出其当前实现仅作为编译器屏障(barrier)使用,已失去原有的抢占禁用功能。文章追溯了相关commit历史,解释了在UP(单处理器)和非抢占内核中,该函数仅需保证编译器不重排代码顺序。同时介绍了配置选项PREEMPT的作用,它通过允许内核代码被抢占来降低延迟,适用于桌面和嵌入式系统。最后阐述了preempt_disable/enable的正确使用场景,包括保护关键代码段、实现原子操作等,并给出了工作队列中的实际应用示例。

mzhan017的博客 656

竞争_LOCK

spin_lock VS spin_lock_irqsave   他们两者只有一个差别:是否调用local_irq_disable()函数, 即是否禁止本地中断。在任何情况下使用spin_lock_irq都是安全的。因为它既禁止本地中断,又禁止内核抢占。spin_lock比spin_lock_irq速度快,但是它并不是任何情况下都是安全的。举个例子:进程A中调用了spin_lock(&lock

Free Bar 807

别只盯着Spectre!Cadence Virtuoso里APS和Spectre X该怎么选?一份给模拟IC新手的指南

本文深入解析Cadence Virtuoso中的三大仿真引擎Spectre、APS和Spectre X,帮助模拟IC新手根据电路规模、精度需求和计算资源做出智能选择。通过对比技术指标和应用场景,提供射频电路、混合信号系统和电源管理IC的优化仿真策略,显著提升设计效率。

weixin_26841743的博客 704

miniDP与DP管脚定义差异详解及设计避坑指南

本文详细解析了Mini DisplayPort与标准DisplayPort接口在管脚定义上的核心差异,通过对比表格直观展示了两者20针脚的不同排列方式,特别是高速差分信号线的分布。文章结合真实设计案例,为硬件工程师提供了从原理图设计、PCB布局到信号完整性考量及故障排查的完整避坑指南,强调绝不能将两者视为简单的物理缩小版。

weixin_29248653的博客 362

Linux内核抢占机制(preempt)

早期的Linux内核(2.5.4版本之前)是不可抢占的。它的调度方法是:一个进程可以通过schedule()函数自愿地启动一次调度。非自愿的强制性调度只能发生在 每次从系统调用返回的前夕以及每次从中断或异常处理返回到用户空间的前夕。但是,如果在系统空间发生中断或异常是不会引起调度的。这种方式使内核实现得以 简化。但常存在下面两个问题: (一)如果这样的中断发生在内核中,本次中断返回是不会引起调度...

kunkliu的博客 1108

Ardupilot姿态控制详解(完结篇)

本文主要是对过去写的一些APM中姿态控制流程及函数博文的汇总。 按照之前写的博文以及个人认为的学习顺序,给出APM姿态控制器的学习顺序如下: APM姿态旋转理论基础 Ardupilot姿态控制器 PID控制流程(整定后的P控制器) 详解APM的开方控制器sqrt_controller Ardupilot前馈及平滑函数input_euler_angle_roll_pitch_yaw解析 Ardupilot倾转分离函数thrust_heading_rotation_angles Ardupilot四元数姿态控制

moumde的博客 7024

linux内核魔法键抢占优先级,Linux内核抢占机制(preempt)

早期的Linux核心是不可抢占的。它的调度方法是:一个进程可以通过schedule()函数自愿地启动一次调度。非自愿的强制性调度只能发生在每次从系统调用返回的前夕以及每次从中断或异常处理返回到用户空间的前夕。但是,如果在系统空间发生中断或异常是不会引起调度的。这种方式使内核实现得以简化。但常存在下面两个问题:如果这样的中断发生在内核中,本次中断返回是不会引起调度的,而要到最初使CPU从用户空间进入...

weixin_42524171的博客 274

机器学习---xgboost算法

问题上表现的十分顶尖,本节将较详细的介绍XGBoost的算法原理。成和剪枝分别对应了经验风险最小化和结构风险最小化, XGBoost的决策树生成是结构风险最小。式(1.1)称为经验风险最小化,训练得到的模型复杂度较高。出结果, 是模型的输出结果;等式右边第⼀部分是模型的训练误差,第⼆部分是正则化项,这里。其中,F是假设空间,假设空间是在已知属性和属性可能取值的情况下,对所有可能满足目标的情。最小化,结构风险最小化的模型往往对训练数据以及未知的测试数据都有较好的预测。的正则化项是K棵树的正则化项相加而来的。

weixin_43961909的博客 1万+

ISP之LSC(Lens Shading Correction)

LSC - Lens Shading Correction即镜头暗影校正。

IQ_WXY的博客 5097

Linux内核深入学习 - 内核同步

在我们开始之前,先来看看内核抢占,他是我们为了解决的东西而引出来的内核同步!

charlie114514191的博客 1439

YOLOv11涨点改进| TGRS 2026 | 独家创新首发、特征融合改进篇| 引入STSAM协同时空注意力融合模块,发论文热点创新,注意力能够互相引导强化边界和结构细节,增强目标检测、图像分割涨点

🔥本文提出了一种改进YOLOv11网络模型的STSAM协同时空注意力融合模块,用于提升高分辨率遥感变化检测的精度。STSAM通过并行处理全局跨时相注意力和局部坐标注意力,能有效聚焦真实变化目标,强化边界和结构细节。该模块包含两个分支:Cross-Attention分支通过时间嵌入增强双时相特征的时间差异,CoordAtt分支则强化局部结构细节。实验表明,STSAM能显著提升变化检测性能,同时保持训练稳定性。文章详细介绍了模块结构、原理、优势,并提供了完整的核心代码实现和配置方法,包括三种改进方案。

Ai缝合怪、助力小伙伴高效发论文 216

linux程序不可抢占,Linux内核抢占机制(preempt)

早期的Linux核心是不可抢占的。它的调度方法是:一个进程可以通过schedule()函数自愿地启动一次调度。非自愿的强制性调度只能发生在每次从系统调用返回的前夕以及每次从中断或异常处理返回到用户空间的前夕。但是,如果在系统空间发生中断或异常是不会引起调度的。这种方式使内核实现得以简化。但常存在下面两个问题:如果这样的中断发生在内核中,本次中断返回是不会引起调度的,而要到最初使CPU从用户空间进入...

weixin_30615531的博客 666

mojoPortal 路径穿越漏洞复现(CVE-2025-28367)(附脚本)

 在 mojoPortal CMS 版本 <=2.9.0.1 中发现了一个导致 ViewState 反序列化的目录遍历漏洞。通过利用此问题,未经身份验证的攻击者可以泄露 Web 根目录中的敏感文件,包括应用程序的文件。此配置文件包含用于验证和解密 ViewState 数据的文件。知道此密钥后,网络攻击者可以构建恶意 ViewState 有效负载,从而导致在底层服务器上执行远程代码。(CVE-2025-28367)

iSee857的博客 500

Python爬虫博客:爬取碳排放交易数据——使用最新技术的完整实现

通过上述方法,我们可以构建一个高效的爬虫,爬取碳排放交易市场的数据并进行分析。这个项目不仅展示了如何处理静态和动态网页,还提供了如何存储数据、分析数据和可视化结果的技巧。随着爬虫技术的不断进步,我们可以进一步提升爬取效率和数据分析能力。如果你希望更深入了解如何进行数据挖掘和机器学习分析,可以尝试将碳排放数据与其他经济数据结合,利用机器学习模型进行趋势预测或决策支持。

2201_76125261的博客 351

Linux内核抢占机制preempt

转自:原文链接早期的Linux核心是不可抢占的。它的调度方法是:一个进程可以通过schedule()函数自愿地启动一次调度。非自愿的强制性调度只能发生在 每次从系统调用返回的前夕以及每次从中断或异常处理返回到用户空间的前夕。但是,如果在系统空间发生中断或异常是不会引起调度的。这种方式使内核实现得以 简化。但常存在下面两个问题:如果这样的中断发生在内核中,本次中断返回是不会引起调度的,而要到最初使C...

LinuxBegin的博客 896

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

内核抢占1

一、什么叫抢占 所谓抢占,说白了就是进程切换。 linux的用户空间,进程A在执行中,来(硬?)中断打断A,从中断处理程序返回时,如果有更高优先级进程B在排队的话,那么执行进程B。 用户空间下进程总是可抢占的 在linux的内核空间就不一定了,linux 2.4是不可抢占的,实时性就会降低,如下面这个样子: 二、抢占的API preempt_enable()  开启抢占

zhyjunFov的专栏 637

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

内核抢占实现(preempt) 【转】

转自:http://blog.chinaunix.net/uid-12461657-id-3353217.html 一、什么叫抢占 所谓抢占,说白了就是进程切换。 linux的用户空间,进程A在执行中,来(硬?)中断打断A,从中断处理程序返回时,如果有更高优先级进程B在排队的话,那么执行进程B。 用户空间下进程总是可抢占的 在linux的内核空间就不一定...

weixin_34273479的博客 172

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

RTOS的基本概念(RT-Thread学习笔记-01)

文章目录前言一、内核类概念1.调度(Scheduling)2.不可抢占型内核与可抢占型内核3.时钟节拍(时间嘀嗒)4.实时性(1)线程调度的时间指标二、正文1.引入库2.读入数据总结 前言 在 RTOS 中,调度与线程是两个最重要概念。 RTOS 的相关术语,简单地分为内核类与线程类的相关术语,理解这些基本概念,是学习 RTOS 的关键一环。 一、内核类概念 在 RTOS 基础上编程,芯片启动过程先运行的一段程序代码,开辟好用户线程的运行环境,准备好对线程进行调度,这段程序代码就是 RTOS 的内核。

qq_35222498的博客 2169
上一篇: 内核抢占1
下一篇: 内核自旋锁spin_lock
zhyjunFov
博客等级 码龄18年 17粉丝 17原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值