Linux中断子系统(四)申请中断request_irq

1. 申请中断 __setup_irq是用于设置和注册中断的核心函数,它是request_threaded_irq等函数的内部实现。 1.1. irqaction handler和thread_fn是struct irqaction的两个重要成员,由程序员指定或在__setup_irq中自动设置, 在中断发生后的处理函数被调用。 1/// include/linux/interrupt.h 2/** 3 * struct irqaction - per interrupt action descriptor 4 * @handler: interrupt handler function 5 * @name: name of...

Linux中断子系统(五)中断处理

1. 中断入口 要处理中断,必须为handle_arch_irq赋值。 ARM64自己定义handle_arch_irq的实现。 1/// arch/arm64/kernel/irq.c 2void (*handle_arch_irq)(struct pt_regs *) __ro_after_init = default_handle_irq; 3void (*handle_arch_fiq)(struct pt_regs *) __ro_after_init = default_handle_fiq; 4 5int __init set_handle_irq(void (*handle_irq)(struct pt_regs...

Linux中断子系统(一)软硬件初始化

1. 简介 early_irq_init完成中断子系统软件部分初始化。 irqchip_init初始化中断控制器,向系统注册struct irq_domain。 2. 中断软件子系统初始化 early_irq_init初始化数组或树,用于保存virq到struct irq_desc的转换关系。 irq_to_desc用于将virq转换为struct irq_desc指针。 2.1. 线性映射 未定义CONFIG_SPARSE_IRQ时使用线性映射,使用数组实现,静态分配,支持的最大virq由NR_IRQS决定。 1struct irq_desc irq_desc[NR_IRQS]...

Linux内核代码的编写和优化技巧

1. Linux内核代码的编写和优化技巧 1.1. 代码编写 使用 __same_type和 typecheck编译时检查类型匹配。 __printf和 __scanf编译时检查代码。 对宏进行undef后重新定义,生成不同的代码,如 __SYSCALL配合 unistd.h生成系统调用,TRACE_EVENT生成ftrace相关的数据结构和各个函数。 使用模板宏,减少重复代码也降低出错率,如 STANDARD_PARAM_DEF生成 module_param用到的set和get函数。 使用内联汇编提升性能。 使用位图优化内存占用。 无锁队列kfifo。 1.2. 控制编译时行为 O2或 O3,编译时优化汇编代码。...

vmalloc原理

1. 全局数据结构 1/// mm/vmalloc.c 2/* Export for kexec only */ 3LIST_HEAD(vmap_area_list); 4static struct rb_root vmap_area_root = RB_ROOT; 5/// ... ... 6 7/* 8 * This kmem_cache is used for vmap_area objects. Instead of 9 * allocating from slab we reuse an object from this cache to 10 * make things faster. Especially in...

ARM64 jump label源码分析

1. 背景 引入jump label的背景,参考Linux: Jump label实现简析 在内核代码中,有很多分支判断条件,它们在绝大多数情形下,都是不成立的。尽管我们已经加上unlikely修饰来进行优化,但是,读取 condition 仍然要访问内存,仍然需要用到cache;另外,也会CPU分支预测失败。虽然少数这样的代码影响不大,但当这样的条件判断代码(如内核中大量的tracepoint)增多的时候,将对cache会造成很大压力,所有这些代码导致的cache miss,以及CPU分支预测失败,所造成的性能损失,就变得可观起来。因此,内核需要一种方案,来解决这样的问题。这个解决方案,就是本文描述的 Jump label。...

ARM64 Linux中断入口

1. 简介 ARM64中断入口相关的代码主要在arch/arm64/kernel/entry.S,启动过程中,会将中断向量表vectors的起始虚拟地址写入到VBAR_EL1。 当发生中断或者异常时,硬件会保存一些寄存器,然后就是软件的工作: 进入中断后,根据中断原因,跳转到对应的中断处理函数,这部分是汇编实现。 在中断处理函数中,先通过kernel_entry将寄存器压栈,然后将栈空间记录的struct pt_regs传递给C语言的对应中断处理函数。 完成中断处理后,根据中断发生的异常等级,决定是调用ret_to_user还是ret_to_kernel退出中断,这两个hasn’t都是对汇编代码kernel_exit的封装。...

Linux fork进程/线程简介

1. kernel_clone kernel_clone是内核创建进程/线程的核心函数,如下功能都是通过调用kernel_clone实现的。 kernel_thread:创建内核进程 user_mode_thread:创建1号进程,1号进程的回调函数先是内核态的kernel_init,之后通过execve切换到用户进程 fork和clone系统调用:创建用户进程/线程 kernel_clone主要流程是copy_process函数实现task_struct结构的创建和初始化,而后通过wake_up_new_task将新进程/线程加入运行队列,并唤醒。详细流程见源码注释。 1/// kernel/sched/core.c 2/* 3...