Interrupt 架构之美 -- Linux Kernel 实现欣赏
2017-12-22 21:11
309 查看
这是以前的浅析 :
http://blog.csdn.net/leesagacious/article/details/50500096
http://blog.csdn.net/leesagacious/article/details/50491819
http://blog.csdn.net/leesagacious/article/details/78679903
http://blog.csdn.net/leesagacious/article/details/50500096
http://blog.csdn.net/leesagacious/article/details/50491819
http://blog.csdn.net/leesagacious/article/details/78679903
注册中断
int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id) { /* 函数中一上来就声明的结构体,其地位都是非常重要的, 作者一上来就想到、就要声明它,大都是该体系中的核心数据结构, 如下的两个结构体蕴含丰富,用到了在说吧, */ struct irqaction *action; struct irq_desc *desc; int retval; /* 绝对不推荐使用共享中断, 1 : SOC支持的中断源数量很多,如 : 256 - 32 = 224个 如果还不够你用, 那你可以选择级联的中断控制器的SOC了 2 : 遍历共享中断处理函数形成的irqaction链表,执行每一个ISR 查看各自的状态寄存器看是否是自己发生了中断, 清中断(163 sts中断在读取该状态寄存器的时候,就被清理了,164 mo中断一定要手动清理(真是一个辣鸡!),否则中断风暴要来了 参见上图) 这延迟了中断处理的时间了吧,与"上半部分执行的越快越好"的理念是违背的 为什么 “上半部分执行的越快越好”,这涉及到了上、下半部分诞生的原因了,下面说 dev_id 是ISR向被中断的进程开了一扇窗,可传一个值,暴力的Interrupt也有温柔的一面,哈哈! 请不要再联想dev_id与共享中断的事情了,说什么free_irq()释放时唯一性的那些东西,因为不推荐共享中断, 加上这个do....while() 是为了处理共享中断情况的,大多数情况下,只会执行一次,因为只有共享中断,链表上 才会有多个irqaction,否则只有一个 请移步: http://blog.csdn.net/leesagacious/article/details/51884483 do { res = action->handler(irq, action->dev_id); 你写的ISR被调用 ..... action = action->next; 下一个 } while (action); */ if ((irqflags & IRQF_SHARED) && !dev_id) return -EINVAL; /* 从Radix Tree中 找到中断描述符 struct irq_desc 上面声明的,下面肯定会有对应的响应的,念念不忘,必有回响,哈哈! 可能会说,不是从数组中根据软件中断号irq对应的数组下标来找到的吗, 以前的kernel确实是用数组来管理的,这又涉及到初始化的部分了,还是下面在说, 关于是 "描述符"的东西 都绝对是核心的东西了,你可能又联想到USB的那些很多描述符了吧, 那么 这里的 irq_desc 描述了哪些属性 ? 你想一下吧,它应该描述哪些东西 return radix_tree_lookup(&irq_desc_tree, irq); 用基数树来管理比用数组来管理有哪些优势 ? 那个惯用的数组下标的经典手法又一次体现出来了 */ desc = irq_to_desc(irq); if (!desc) return -EINVAL; /* 中断描述符是一种资源,预先分配好的,这个不像 进程的ID 使用延迟重用算法 和 文件描述符fd 那样的动态 分配的了, 有些是不可以用的, 源码 : return !(desc->status_use_accessors & _IRQ_NOREQUEST); return desc->status_use_accessors & _IRQ_PER_CPU_DEVID; irq_desc是怎么被初始化的,下面说,这里先把这个函数流程执行完成 */ if (!irq_settings_can_request(desc) || WARN_ON(irq_settings_is_per_cpu_devid(desc))) return -EINVAL; /* handler你不给,thread_fn你也不给,你让Interrupt做什么呢? 如果鱼与熊掌偏偏都给你了,下面看看Interrupt是怎么做的 ? 好,这里就是 该函数的核心的地方了 ! */ if (!handler) { if (!thread_fn) return -EINVAL; /* return IRQ_WAKE_THREAD; 就一句话,它要唤醒中断线程. 那么要问了, 1 : 中断线程是在什么时机被二号进程 kthreadd 产生的 ? 2 : 又是再什么时机被唤醒的 多说一句,内核线程大都是这个样子,一上来就睡,对应的条件出发了,再去唤醒它, 就像Hub的驱动 khubd内核线程一样,hub上的port被接入了usb设备后,它就被唤醒了 来枚举Port上的设备了, 但是,这个内核线程来头可不一般 ! */ handler = irq_default_primary_handler; } /* 分配内存空间吧,这里就是 irqaction的起点了. 终点在哪 ? 当然是 free_irq()了,有分配,必有释放,哈哈! */ action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; /* 利用传入的参数 给它赋值,然后挂入链表 这里想到了signal挂入链表的情景,但是,这里的是单链表, 且在执行的时候,无需查找链表节点的,而是一次全部触发(共享中断) 看,上面是一大串校验,这里才开始实际的工作. */ action->handler = handler; action->thread_fn = thread_fn; action->flags = irqflags; // 关注这个 flags这个值,做一个标记. action->name = devname; action->dev_id = dev_id; chip_bus_lock(desc); /* 主角 终于要粉墨登场了! */ retval = __setup_irq(irq, desc, action); chip_bus_sync_unlock(desc); if (retval) kfree(action); }
/** 这个函数很长,做的事情很多 @irq : 软件中断号, @desc : 中断源描述符 @irqaction : 中断动作描述符 ,既然是动作描述符,那么一定会有pointer指向你写的ISR. */ static int __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) { struct irqaction *old, **old_ptr; unsigned long flags, thread_mask = 0; int ret, nested, shared = 0; cpumask_var_t mask; }
相关文章推荐
- Usb + Serial + Net --- Linux Kernel 实现欣赏
- 往process group 发送signal - linux kernel 实现浅欣赏
- uevent内核事件与netlink机制的交互 -Linux Kernel实现欣赏
- Uart 架构之美 -- Linux Kernel 实现浅析
- Linux Kernel 调度实现 -----欣赏
- Driver 分层的思想 -- Linux Kernel 内核实现欣赏
- genl-netlink 协议 Linux kernel 实现 欣赏
- Process scheduling - Linux Kernel 实现 欣赏
- Device Tree --- Linux Kernel 实现欣赏
- Spring技术内幕——深入解析Spring架构与设计原理(一)IOC实现原理
- EF6的多线程与分库架构设计实现
- MVC 之 架构的基本原理及Asp.Net实现MVC
- ELK(elasticsearch+logstash+kibana)实现Java分布式系统日志分析架构
- mysql+mha+keepalived实现MHA架构
- 以大数据眼光欣赏唐人文墨(二)代码实现
- gtest实现架构简单分析
- 淘宝网采用什么技术架构来实现网站高负载的
- JDBC:DAO(三)利用queryRunner实现一个较好的DAO架构
- linux kernel中epoll的设计和实现
- 软件架构实现