Preempt-RT --- Linux kernel 实现欣赏

static int __init irqpoll_setup(char *str)
{
#ifdef CONFIG_PREEMPT_RT
	pr_warn("irqpoll boot option not supported w/ CONFIG_PREEMPT_RT\n");
	return 1;
#endif

	irqfixup = 2;
	printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
				"enabled\n");
	printk(KERN_WARNING "This may significantly impact system "
				"performance\n");
	return 1;
}

__setup("irqpoll", irqpoll_setup);

在这里插入图片描述
先看下面一个interrupt的流程, 然后解释noirqdebug 存在的意义.
如果 noirqdebug 为 true, 那么 irqpoll_setup 的存在是 no value !

Linux 内核中没任何模块能绝对“独立”,相互的关系是绝对的,但是独立是相对的.
在这里插入图片描述
在这里插入图片描述

/*
 *: 先来看 interrupt 到底是什么
 *     1 : 中断是响应外部硬件设备的一个机制 (包括时钟中断)
 *         例如 : 
 * 				时钟中断中更新task的vruntime 、cfs->min_vruntime 以及查看能否抢占 (它委托给一个函数来实现 : entity_tick())
 *     2 : 中断是系统中的一个事件(即一个Event) 
 *         (具体的可参见 Intel manual .)     
 * 
 *    ok !
 * 
 *    Force interrupt threading 后,它就成为了一个优先级为50的实时进程,可以被更高优先级的进程抢占了, 
 * 
 *   😄哈哈,interrupt终于被拉下了神坛, 也就是说中断可以延迟被执行了.
 * 
 *    如果这个isr中要获取的数据实时性很高,不能被延迟执行,那么就保留原来朴素的中断.: 反线程化.
 * 
 *    那么既然是一个进程了,那么workqueue也是进程 它们有什么样的异同呢.
 *    当然有异同了,且大大的异同,
 *    比如说 调度策略,一个是 SCHED_FIFO 一个是SCHED_NORMAL, workqueue靠边站,瘦死的骆驼也比你workqueue大 !
 */
irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
{
	/*
		原来的code,这里暂且不讲,让我们专注于 PREEMET_RT
	*/
	irqreturn_t retval;
	unsigned int flags = 0;
	
	/*
	 *    获取 pt_regs.
	 *    ok, 什么是 pt_regs, 这里为什么要获取它
	 *    哈哈😄 别忘记中断现场保存在哪里的, 这里要用到了.
	 *    ok,我们把保存中断现场的那段code拿出来,看一下.
	 */
	struct pt_regs *regs = get_irq_regs();				
	u64 ip = regs ? instruction_pointer(regs) : 0;
	
	retval = __handle_irq_event_percpu(desc, &flags);
	
#ifdef CONFIG_PREEMPT_RT
	desc->random_ip = ip;
#else
	add_interrupt_randomness(desc->irq_data.irq, flags, ip);
#endif

	if (!noirqdebug)
		note_interrupt(desc, retval);
	return retval;
}

在这里插入图片描述

struct pt_regs {
	union {
		struct user_pt_regs user_regs;
		struct {
			/*
			 *    X0 X1 .... X20 X30 寄存器.
			 *    SP寄存器
			 *    PC寄存器
			 *    PSTATE 寄存器.
 			 */
			u64 regs[31];
			u64 sp;
			u64 pc;
			u64 pstate;
		};
	};
	u64 orig_x0;
#ifdef __AARCH64EB__       /* 大端字节序 */
	u32 unused2;
	s32 syscallno;
#else					   	
	s32 syscallno;
	u32 unused2;
#endif
	u64 sdei_ttbr1;
	u64 pmr_save;
	u64 stackframe[2];
	u64 lockdep_hardirqs;
	u64 exit_rcu;
};
要判断您的系统是否已成功部署 Preempt-RT,可以通过以下几种方法进行验证: ### 方法一:检查内核版本 通过 `uname -r` 命令查看当前正在使用的内核版本。如果内核名称中包含 `-rt` 或者类似字样(例如:5.4.0-rc8-rt7),则表明您正在使用的是打了 RT 补丁的内核。 ```bash $ uname -r 5.4.0-rc8-rt7-amd64 ``` ### 方法二:查找内核配置文件 进入 `/boot/config-$(uname -r)` 文件路径下找到对应内核的 `.config` 配置文件,搜索是否存在 `CONFIG_PREEMPT_RT` 这一项及其状态。若该项被设置为 "y" 则代表启用了全抢占式实时功能;如果是 "m", 就表示其作为一个模块加载进来了; 而如果没有这项内容的话就说明没有开启该特性。 ```bash grep CONFIG_PREEMPT_RT /boot/config-$(uname -r) # 输出应类似于下面的结果: # CONFIG_PREEMPT_RT=y ``` ### 方法三:使用 dmesg 检查日志信息 启动完成后立即运行 `dmesg | grep PREEMPT`, 系统会打印出有关 preempt 类型的信息。对于标准非实时 Linux 来讲一般显示的是“Preemption model None”,而在应用了 Preempt-RT 后,则可能会看到如下这样的消息:“Preemption model Fully Preemptible Kernel”。 ```bash dmesg | grep PREEMPT [ 0.000000] Command line: root=/dev/sda2 ro quiet splash preempt=fully [ 0.000000] PREEMPT RT Model is fully preemtible kernel. ``` 以上三种方式都可以帮助我们有效地确认 Preempt-RT 是否已经被正确地集成到了我们的环境之中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值