首页 > 其他分享 >保持内核代码的可抢占安全 【ChatGPT】

保持内核代码的可抢占安全 【ChatGPT】

时间:2023-12-10 12:13:12浏览次数:28  
标签:抢占 cc 禁用 preempt 内核 ChatGPT CPU

在可抢占内核下的适当锁定:保持内核代码的可抢占安全

作者 Robert Love [email protected]

介绍

可抢占内核会引发新的锁定问题。这些问题与SMP下的问题相同:并发性和可重入性。幸运的是,Linux可抢占内核模型利用了现有的SMP锁定机制。因此,内核只需要为极少数情况显式添加额外的锁定。

本文适用于所有内核开发者。在内核中开发代码需要保护这些情况。

规则1:每个CPU的数据结构需要显式保护

会出现两个类似的问题。一个示例代码片段:

struct this_needs_locking tux[NR_CPUS];
tux[smp_processor_id()] = some_value;
/* 任务在此处被抢占... */
something = tux[smp_processor_id()];

首先,由于数据是每个CPU的,它可能没有显式的SMP锁定,但在其他情况下需要它。其次,当一个被抢占的任务最终被重新调度时,smp_processor_id的先前值可能不等于当前值。你必须通过在它们周围禁用抢占来保护这些情况。

你还可以使用put_cpu()和get_cpu(),它们会禁用抢占。

规则2:必须保护CPU状态。

在抢占下,必须保护CPU的状态。这是与体系结构相关的,但包括CPU结构和在上下文切换中不保留的状态。例如,在x86上,进入和退出FPU模式现在是一个必须在禁用抢占时发生的临界区。想象一下,如果内核正在执行一个浮点指令,然后被抢占了会发生什么。请记住,内核除了用户任务外不保存FPU状态。因此,在抢占时,FPU寄存器将被卖给出价最低的人。因此,在这样的区域周围必须禁用抢占。

注意,一些FPU函数已经明确支持抢占安全。例如,kernel_fpu_begin和kernel_fpu_end会禁用和启用抢占。

规则3:锁的获取和释放必须由同一任务执行

在一个任务中获取的锁必须由同一任务释放。这意味着你不能做一些奇怪的事情,比如获取一个锁然后去做其他事情,而另一个任务释放它。如果你想做类似的事情,需要在同一代码路径中获取和释放锁,并让调用者等待另一个任务的事件。

解决方案

在抢占期间通过禁用抢占来实现对数据的保护。

preempt_enable()              减少抢占计数器
preempt_disable()             增加抢占计数器
preempt_enable_no_resched()   减少计数器,但不立即抢占
preempt_check_resched()       如果需要,重新调度
preempt_count()               返回抢占计数器的值

这些函数是可嵌套的。换句话说,在代码路径中可以多次调用preempt_disable,直到第n次调用preempt_enable之前,抢占不会被重新启用。如果未启用抢占,则preempt语句不起作用。

请注意,如果你持有任何锁或中断被禁用,你不需要显式地防止抢占,因为在这些情况下,抢占会被隐式禁用。

但请记住,“中断禁用”是一种基本不安全的禁用抢占的方式——如果抢占计数为0,任何cond_resched()或cond_resched_lock()都可能触发重新调度。一个简单的printk()可能会触发重新调度。因此,只有在你知道受影响的代码路径不执行任何这样的操作时,才使用这种隐式禁用抢占的属性。最好的策略是只在你编写的小型原子代码中使用这种属性,该代码不调用任何复杂的函数。

示例:

cpucache_t *cc; /* 这是每个CPU的 */
preempt_disable();
cc = cc_data(searchp);
if (cc && cc->avail) {
        __free_block(searchp, cc_entry(cc), cc->avail);
        cc->avail = 0;
}
preempt_enable();
return 0;

注意如何使抢占语句包围每个关键变量的引用。另一个示例:

int buf[NR_CPUS];
set_cpu_val(buf);
if (buf[smp_processor_id()] == -1) printf(KERN_INFO "wee!\n");
spin_lock(&buf_lock);
/* ... */

这段代码不是抢占安全的,但是看看我们如何通过简单地将spin_lock向上移动两行来修复它。

使用禁用中断来防止抢占

可以使用local_irq_disable和local_irq_save来防止抢占事件。注意,这样做时,必须非常小心,不要引发会设置need_resched并导致抢占检查的事件。如果不确定,可以依靠锁定或显式禁用抢占。

请注意,在2.5版本中,禁用中断现在只是每个CPU的(例如,local)。

另一个问题是正确使用local_irq_disable和local_irq_save。它们可以用于防止抢占,但是在退出时,如果可能启用抢占,应该进行检查以确定是否需要抢占。如果它们是从spin_lock和read/write lock宏中调用的,那么就会做正确的事情。它们也可以在受spin-lock保护的区域内调用,但是如果它们在这个上下文之外被调用,应该进行抢占的检查。请注意,来自中断上下文或底半部/任务队列的调用也受到抢占锁的保护,因此可以使用不检查抢占的版本。

标签:抢占,cc,禁用,preempt,内核,ChatGPT,CPU
From: https://www.cnblogs.com/pengdonglin137/p/17892351.html

相关文章

  • 序列计数器和顺序锁 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/seqlock.html#序列计数器和顺序锁介绍序列计数器是一种具有无锁读取器(只读重试循环)和无写入者饥饿的读者-写者一致性机制。它们用于很少写入数据的情况(例如系统时间),其中读者希望获得一致的信息集,并且愿意在信息发生变化时重试......
  • 锁定课程 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/spinlocks.html锁定课程课程1:自旋锁用于锁定的最基本原语是自旋锁:staticDEFINE_SPINLOCK(xxx_lock);unsignedlongflags;spin_lock_irqsave(&xxx_lock,flags);...临界区域...spin_unlock_irqrestore(&xxx_lock,fl......
  • RT-mutex 实现设计【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/rt-mutex-design.htmlRT-mutex实现设计版权所有(c)2006StevenRostedt根据GNU自由文档许可证第1.2版许可本文档试图描述rtmutex.c实现的设计。它并不描述rtmutex.c存在的原因。有关此内容,请参阅带PI支持的RT-m......
  • 通用互斥子系统 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/mutex-design.html通用互斥子系统由[email protected]发起由[email protected]更新互斥锁是什么?在Linux内核中,互斥锁指的是一种特定的锁原语,它在共享内存系统上强制进行串行化,而不仅仅是指学术界......
  • 锁统计 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/lockstat.html锁统计什么顾名思义,它提供了有关锁的统计信息。为什么因为诸如锁争用之类的问题会严重影响性能。如何Lockdep已经在锁函数中设置了钩子,并将锁实例映射到锁类上。我们在此基础上构建(参见运行时锁正确性验证器)......
  • 运行时锁定正确性验证器 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/lockdep-design.html锁类该验证器操作的基本对象是“锁”的“类”。“锁”的“类”是一组逻辑上相同的锁,即使这些锁可能有多个(可能有成千上万个)实例化。例如,inode结构中的锁是一个类,而每个inode都有自己的该锁类的实例化。验......
  • Locking (ChatGPT)
    原文:https://www.kernel.org/doc/html/latest/locking/index.html锁定锁类型及其规则运行时锁正确性验证器锁统计信息内核锁折磨测试操作通用互斥子系统实时互斥锁实现设计带有PI支持的实时互斥锁子系统序列计数器和顺序锁锁定教训无伤害/等待死锁安全互斥锁设计在......
  • 锁类型及其规则 【ChatGPT】
    https://www.kernel.org/doc/html/latest/locking/locktypes.html锁类型及其规则介绍内核提供了各种锁原语,可以分为三类:睡眠锁CPU本地锁自旋锁本文概念上描述了这些锁类型,并提供了它们的嵌套规则,包括在PREEMPT_RT下的使用规则。锁类别睡眠锁睡眠锁只能在可抢占的......
  • RDMA 控制器 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/admin-guide/cgroup-v1/rdma.htmlRDMA控制器1.概述1-1.什么是RDMA控制器?RDMA控制器允许用户限制给定一组进程可以使用的RDMA/IB特定资源。这些进程是使用RDMA控制器进行分组的。RDMA控制器定义了可以为cgroup的进程限制......
  • 内存资源控制器实现备忘 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/admin-guide/cgroup-v1/memcg_test.htmlMemoryResourceController(Memcg)ImplementationMemo最后更新时间:2010/2基础内核版本:基于2.6.33-rc7-mm(34版本的候选版本)。由于虚拟内存变得复杂(其中一个原因是memcg...),memcg的行为也变得......