linux 中断机制浅析

一、中断相关结构体

1.irq_desc中断描述符

[cpp] view plain copy

  1. struct irq_desc {
  2. #ifdef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
  3. struct irq_data irq_data;
  4. #else
  5. union {
  6. struct irq_data irq_data;   //中断数据
  7. struct {
  8. unsigned int    irq;    //中断号
  9. unsigned int    node;   //节点号
  10. struct irq_chip *chip;  //irq_chip
  11. void    *handler_data;
  12. void    *chip_data;
  13. struct msi_desc *msi_desc;
  14. #ifdef CONFIG_SMP
  15. cpumask_var_t   affinity;
  16. #endif
  17. };
  18. };
  19. #endif
  20. struct timer_rand_state *timer_rand_state;
  21. unsigned int    *kstat_irqs;
  22. irq_flow_handler_t  handle_irq; //中断处理句柄
  23. struct irqaction    *action;    /* 中断动作列表 */
  24. unsigned int    status;     /* 中断状态 */
  25. unsigned int    depth;      /* nested irq disables */
  26. unsigned int    wake_depth; /* nested wake enables */
  27. unsigned int    irq_count;  /* For detecting broken IRQs */
  28. unsigned long   last_unhandled; /* Aging timer for unhandled count */
  29. unsigned int    irqs_unhandled;
  30. raw_spinlock_t  lock;
  31. #ifdef CONFIG_SMP
  32. const struct cpumask    *affinity_hint;
  33. #ifdef CONFIG_GENERIC_PENDING_IRQ
  34. cpumask_var_t   pending_mask;
  35. #endif
  36. #endif
  37. atomic_t    threads_active;
  38. wait_queue_head_t   wait_for_threads;
  39. #ifdef CONFIG_PROC_FS
  40. struct proc_dir_entry   *dir;   //proc接口目录
  41. #endif
  42. const char  *name;  //名字
  43. } ____cacheline_internodealigned_in_smp;

2.irq_chip 芯片相关的处理函数集合

[cpp] view plain copy

  1. struct irq_chip {   //芯片相关的处理函数集合
  2. const char  *name;  //"proc/interrupts/name"
  3. #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
  4. unsigned int    (*startup)(unsigned int irq);
  5. void    (*shutdown)(unsigned int irq);
  6. void    (*enable)(unsigned int irq);
  7. void    (*disable)(unsigned int irq);
  8. void    (*ack)(unsigned int irq);
  9. void    (*mask)(unsigned int irq);
  10. void    (*mask_ack)(unsigned int irq);
  11. void    (*unmask)(unsigned int irq);
  12. void    (*eoi)(unsigned int irq);
  13. void    (*end)(unsigned int irq);
  14. int     (*set_affinity)(unsigned int irq,const struct cpumask *dest);
  15. int     (*retrigger)(unsigned int irq);
  16. int     (*set_type)(unsigned int irq, unsigned int flow_type);
  17. int     (*set_wake)(unsigned int irq, unsigned int on);
  18. void    (*bus_lock)(unsigned int irq);
  19. void    (*bus_sync_unlock)(unsigned int irq);
  20. #endif
  21. unsigned int    (*irq_startup)(struct irq_data *data);  //中断开始
  22. void    (*irq_shutdown)(struct irq_data *data); //中断关闭
  23. void    (*irq_enable)(struct irq_data *data);   //中断使能
  24. void    (*irq_disable)(struct irq_data *data);  //中断禁用
  25. void    (*irq_ack)(struct irq_data *data);
  26. void    (*irq_mask)(struct irq_data *data);
  27. void    (*irq_mask_ack)(struct irq_data *data);
  28. void    (*irq_unmask)(struct irq_data *data);
  29. void    (*irq_eoi)(struct irq_data *data);
  30. int     (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
  31. int     (*irq_retrigger)(struct irq_data *data);
  32. int     (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
  33. int     (*irq_set_wake)(struct irq_data *data, unsigned int on);
  34. void    (*irq_bus_lock)(struct irq_data *data);
  35. void    (*irq_bus_sync_unlock)(struct irq_data *data);
  36. #ifdef CONFIG_IRQ_RELEASE_METHOD
  37. void    (*release)(unsigned int irq, void *dev_id);
  38. #endif
  39. };

3.irqaction中断行动结构体

[cpp] view plain copy

  1. struct irqaction {
  2. irq_handler_t handler;  //中断处理函数
  3. unsigned long flags;    //中断标志
  4. const char *name;       //中断名
  5. void *dev_id;       //设备id号,共享中断用
  6. struct irqaction *next; //共享中断类型指向下一个irqaction
  7. int irq;            //中断号
  8. struct proc_dir_entry *dir; //proc接口目录
  9. irq_handler_t thread_fn;    //中断处理函数(线程)
  10. struct task_struct *thread; //线程任务
  11. unsigned long thread_flags; //线程标志
  12. };

在整个中断系统中将勾勒出以下的关系框图

二、中断初始化工作

从start_kernel看起,大致按以下的分支顺序初始化

[cpp] view plain copy

  1. start_kernel
  2. setup_arch          //设置全局init_arch_irq函数
  3. early_trap_init //搬移向量表
  4. early_irq_init();   //初始化全局irq_desc数组
  5. init_IRQ();         //调用init_arch_irq函数
  6. [   //板级中断初始化常用到的API
  7. set_irq_chip
  8. set_irq_handler
  9. set_irq_chained_handler
  10. set_irq_flags
  11. set_irq_type
  12. set_irq_chip_data
  13. set_irq_data
  14. ]

1.在setup_arch中主要是设置全局init_arch_irq函数

[cpp] view plain copy

  1. void __init setup_arch(char **cmdline_p)
  2. {
  3. struct tag *tags = (struct tag *)&init_tags;
  4. struct machine_desc *mdesc;
  5. char *from = default_command_line;
  6. init_tags.mem.start = PHYS_OFFSET;
  7. unwind_init();
  8. setup_processor();
  9. mdesc = setup_machine(machine_arch_type);
  10. machine_name = mdesc->name;
  11. if (mdesc->soft_reboot)
  12. reboot_setup("s");
  13. if (__atags_pointer)
  14. tags = phys_to_virt(__atags_pointer);
  15. else if (mdesc->boot_params) {
  16. #ifdef CONFIG_MMU
  17. if (mdesc->boot_params < PHYS_OFFSET ||mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
  18. printk(KERN_WARNING"Default boot params at physical 0x%08lx out of reach\n",mdesc->boot_params);
  19. }
  20. else
  21. #endif
  22. {
  23. tags = phys_to_virt(mdesc->boot_params);
  24. }
  25. }
  26. #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
  27. if (tags->hdr.tag != ATAG_CORE)
  28. convert_to_tag_list(tags);
  29. #endif
  30. if (tags->hdr.tag != ATAG_CORE)
  31. tags = (struct tag *)&init_tags;
  32. if (mdesc->fixup)
  33. mdesc->fixup(mdesc, tags, &from, &meminfo);
  34. if (tags->hdr.tag == ATAG_CORE) {
  35. if (meminfo.nr_banks != 0)
  36. squash_mem_tags(tags);
  37. save_atags(tags);
  38. parse_tags(tags);
  39. }
  40. init_mm.start_code = (unsigned long) _text;
  41. init_mm.end_code   = (unsigned long) _etext;
  42. init_mm.end_data   = (unsigned long) _edata;
  43. init_mm.brk    = (unsigned long) _end;
  44. strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
  45. strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
  46. *cmdline_p = cmd_line;
  47. parse_early_param();
  48. arm_memblock_init(&meminfo, mdesc);
  49. paging_init(mdesc);
  50. request_standard_resources(&meminfo, mdesc);
  51. #ifdef CONFIG_SMP
  52. if (is_smp())
  53. smp_init_cpus();
  54. #endif
  55. reserve_crashkernel();
  56. cpu_init();
  57. tcm_init();
  58. arch_nr_irqs = mdesc->nr_irqs;
  59. init_arch_irq = mdesc->init_irq; //设置全局init_arch_irq函数
  60. //void (*init_arch_irq)(void) __initdata = NULL;
  61. system_timer = mdesc->timer;
  62. init_machine = mdesc->init_machine;
  63. #ifdef CONFIG_VT
  64. #if defined(CONFIG_VGA_CONSOLE)
  65. conswitchp = &vga_con;
  66. #elif defined(CONFIG_DUMMY_CONSOLE)
  67. conswitchp = &dummy_con;
  68. #endif
  69. #endif
  70. early_trap_init();//调用early_trap_init函数
  71. }

1.1.early_trap_init主要挪移了中断向量表到特定位置

[cpp] view plain copy

  1. void __init early_trap_init(void)
  2. {
  3. unsigned long vectors = CONFIG_VECTORS_BASE;    //0xffff0000
  4. extern char __stubs_start[], __stubs_end[];
  5. extern char __vectors_start[], __vectors_end[];
  6. extern char __kuser_helper_start[], __kuser_helper_end[];
  7. int kuser_sz = __kuser_helper_end - __kuser_helper_start;
  8. memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);  //移动中断向量表
  9. memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);    //移动__stubs_start段
  10. memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
  11. kuser_get_tls_init(vectors);
  12. memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,sizeof(sigreturn_codes));
  13. memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,sizeof(syscall_restart_code));
  14. flush_icache_range(vectors, vectors + PAGE_SIZE);
  15. modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
  16. }

2.early_irq_init 初始化全局irq_desc数组
在(kernel/irqs/irqdesc.c)中定义了全局irq_desc数组

[cpp] view plain copy

  1. struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
  2. [0 ... NR_IRQS-1] = {
  3. .status     = IRQ_DEFAULT_INIT_FLAGS,
  4. .handle_irq = handle_bad_irq,
  5. .depth      = 1,
  6. .lock       = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
  7. }
  8. };

获取irq_desc数组项的宏

[cpp] view plain copy

  1. #define irq_to_desc(irq)    (&irq_desc[irq])

early_irq_init函数

[cpp] view plain copy

  1. int __init early_irq_init(void) //初始化全局irq_desc数组
  2. {
  3. int count, i, node = first_online_node;
  4. struct irq_desc *desc;
  5. init_irq_default_affinity();
  6. printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
  7. desc = irq_desc;    //获取全局irq_desc数组
  8. count = ARRAY_SIZE(irq_desc);   //获取全局irq_desc数组项个数
  9. for (i = 0; i < count; i++) {    //初始化全局irq_desc数组
  10. desc[i].irq_data.irq = i;
  11. desc[i].irq_data.chip = &no_irq_chip;
  12. desc[i].kstat_irqs = kstat_irqs_all[i];
  13. alloc_masks(desc + i, GFP_KERNEL, node);
  14. desc_smp_init(desc + i, node);
  15. lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
  16. }
  17. return arch_early_irq_init();
  18. }

3.init_IRQ函数调用全局init_arch_irq函数,进入板级初始化

[cpp] view plain copy

  1. void __init init_IRQ(void)
  2. {
  3. init_arch_irq();    //调用板级驱动的中断初始化函数
  4. }

4.板级中断初始化常用到的API

1.set_irq_chip 通过irq中断号获取对应全局irq_desc数组项,并设置其irq_data.chip指向传递进去的irq_chip指针

[cpp] view plain copy

  1. int set_irq_chip(unsigned int irq, struct irq_chip *chip)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. unsigned long flags;
  5. if (!desc) {
  6. WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
  7. return -EINVAL;
  8. }
  9. if (!chip)                      //若irq_chip不存在
  10. chip = &no_irq_chip;        //设置为no_irq_chip
  11. raw_spin_lock_irqsave(&desc->lock, flags);
  12. irq_chip_set_defaults(chip);    //初始化irq_chip
  13. desc->irq_data.chip = chip;      //设置irq_desc->irq_data.chip
  14. raw_spin_unlock_irqrestore(&desc->lock, flags);
  15. return 0;
  16. }
  17. EXPORT_SYMBOL(set_irq_chip);

1.1 irq_chip_set_defaults 根据irq_chip的实际情况初始化默认方法

[cpp] view plain copy

  1. void irq_chip_set_defaults(struct irq_chip *chip)   //根据irq_chip的实际情况初始化默认方法
  2. {
  3. #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
  4. if (chip->enable)
  5. chip->irq_enable = compat_irq_enable;
  6. if (chip->disable)
  7. chip->irq_disable = compat_irq_disable;
  8. if (chip->shutdown)
  9. chip->irq_shutdown = compat_irq_shutdown;
  10. if (chip->startup)
  11. chip->irq_startup = compat_irq_startup;
  12. #endif
  13. if (!chip->irq_enable)       //使能中断
  14. chip->irq_enable = default_enable;
  15. if (!chip->irq_disable)      //禁用中断
  16. chip->irq_disable = default_disable;
  17. if (!chip->irq_startup)      //中断开始
  18. chip->irq_startup = default_startup;
  19. if (!chip->irq_shutdown) //关闭中断
  20. chip->irq_shutdown = chip->irq_disable != default_disable ? chip->irq_disable : default_shutdown;
  21. #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
  22. if (!chip->end)
  23. chip->end = dummy_irq_chip.end;
  24. if (chip->bus_lock)
  25. chip->irq_bus_lock = compat_bus_lock;
  26. if (chip->bus_sync_unlock)
  27. chip->irq_bus_sync_unlock = compat_bus_sync_unlock;
  28. if (chip->mask)
  29. chip->irq_mask = compat_irq_mask;
  30. if (chip->unmask)
  31. chip->irq_unmask = compat_irq_unmask;
  32. if (chip->ack)
  33. chip->irq_ack = compat_irq_ack;
  34. if (chip->mask_ack)
  35. chip->irq_mask_ack = compat_irq_mask_ack;
  36. if (chip->eoi)
  37. chip->irq_eoi = compat_irq_eoi;
  38. if (chip->set_affinity)
  39. chip->irq_set_affinity = compat_irq_set_affinity;
  40. if (chip->set_type)
  41. chip->irq_set_type = compat_irq_set_type;
  42. if (chip->set_wake)
  43. chip->irq_set_wake = compat_irq_set_wake;
  44. if (chip->retrigger)
  45. chip->irq_retrigger = compat_irq_retrigger;
  46. #endif
  47. }

2.set_irq_handler和set_irq_chained_handler

这两个函数的功能是:根据irq中断号,获取对应全局irq_desc数组项,并将数组项描述符的handle_irq中断处理函数指针指向handle
如果是chain类型则添加数组项的status状态IRQ_NOREQUEST和IRQ_NOPROBE属性

[cpp] view plain copy

  1. static inline void set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
  2. {
  3. __set_irq_handler(irq, handle, 0, NULL);    //调用__set_irq_handler
  4. }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

[cpp] view plain copy

  1. static inline void set_irq_chained_handler(unsigned int irq,irq_flow_handler_t handle)
  2. {
  3. __set_irq_handler(irq, handle, 1, NULL);    //调用__set_irq_handler
  4. }

2.1 __set_irq_handler函数

[cpp] view plain copy

  1. void __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,const char *name)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. unsigned long flags;
  5. if (!desc) {
  6. printk(KERN_ERR"Trying to install type control for IRQ%d\n", irq);
  7. return;
  8. }
  9. if (!handle)    //若没指定handle
  10. handle = handle_bad_irq;    //则设置为handle_bad_irq
  11. else if (desc->irq_data.chip == &no_irq_chip) {
  12. printk(KERN_WARNING "Trying to install %sinterrupt handler for IRQ%d\n", is_chained ? "chained " : "", irq);
  13. desc->irq_data.chip = &dummy_irq_chip;   //设置desc->irq_data.chip为dummy_irq_chip(空操作的irq_chip)
  14. }
  15. chip_bus_lock(desc);
  16. raw_spin_lock_irqsave(&desc->lock, flags);
  17. if (handle == handle_bad_irq) {
  18. if (desc->irq_data.chip != &no_irq_chip)
  19. mask_ack_irq(desc);
  20. desc->status |= IRQ_DISABLED;
  21. desc->depth = 1;
  22. }
  23. desc->handle_irq = handle;   //高级中断处理句柄
  24. desc->name = name;
  25. if (handle != handle_bad_irq && is_chained) {   //链接
  26. desc->status &= ~IRQ_DISABLED;
  27. desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
  28. desc->depth = 0;
  29. desc->irq_data.chip->irq_startup(&desc->irq_data);
  30. }
  31. raw_spin_unlock_irqrestore(&desc->lock, flags);
  32. chip_bus_sync_unlock(desc);
  33. }
  34. EXPORT_SYMBOL_GPL(__set_irq_handler);

3.set_irq_flags 根据irq号获取全局irq_desc数组项,并设置其status标志(中断标志)

[cpp] view plain copy

  1. void set_irq_flags(unsigned int irq, unsigned int iflags)
  2. {
  3. struct irq_desc *desc;
  4. unsigned long flags;
  5. if (irq >= nr_irqs) {
  6. printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
  7. return;
  8. }
  9. desc = irq_to_desc(irq);    //获取全局irq_desc数组项
  10. raw_spin_lock_irqsave(&desc->lock, flags);
  11. desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
  12. if (iflags & IRQF_VALID)
  13. desc->status &= ~IRQ_NOREQUEST;
  14. if (iflags & IRQF_PROBE)
  15. desc->status &= ~IRQ_NOPROBE;
  16. if (!(iflags & IRQF_NOAUTOEN))
  17. desc->status &= ~IRQ_NOAUTOEN;
  18. raw_spin_unlock_irqrestore(&desc->lock, flags);
  19. }

4.set_irq_type根据irq号获取全局irq_desc数组项,并设置其status标志(中断触发类型)

[cpp] view plain copy

  1. int set_irq_type(unsigned int irq, unsigned int type)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. unsigned long flags;
  5. int ret = -ENXIO;
  6. if (!desc) {
  7. printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
  8. return -ENODEV;
  9. }
  10. type &= IRQ_TYPE_SENSE_MASK;
  11. if (type == IRQ_TYPE_NONE)
  12. return 0;
  13. raw_spin_lock_irqsave(&desc->lock, flags);
  14. ret = __irq_set_trigger(desc, irq, type);   //调用__irq_set_trigger
  15. raw_spin_unlock_irqrestore(&desc->lock, flags);
  16. return ret;
  17. }
  18. EXPORT_SYMBOL(set_irq_type);

4.1 __irq_set_trigger函数

[cpp] view plain copy

  1. int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,unsigned long flags)
  2. {
  3. int ret;
  4. struct irq_chip *chip = desc->irq_data.chip;
  5. if (!chip || !chip->irq_set_type) {
  6. pr_debug("No set_type function for IRQ %d (%s)\n", irq,chip ? (chip->name ? : "unknown") : "unknown");
  7. return 0;
  8. }
  9. ret = chip->irq_set_type(&desc->irq_data, flags);
  10. if (ret)
  11. pr_err("setting trigger mode %lu for irq %u failed (%pF)\n",flags, irq, chip->irq_set_type);
  12. else {
  13. if (flags & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
  14. flags |= IRQ_LEVEL;
  15. /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
  16. desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
  17. desc->status |= flags;
  18. if (chip != desc->irq_data.chip)
  19. irq_chip_set_defaults(desc->irq_data.chip);
  20. }
  21. return ret;
  22. }

5.set_irq_chip_data 根据irq号获取全局irq_desc数组项,并设置其irq_data的chip_data

[cpp] view plain copy

  1. int set_irq_chip_data(unsigned int irq, void *data)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. unsigned long flags;
  5. if (!desc) {
  6. printk(KERN_ERR"Trying to install chip data for IRQ%d\n", irq);
  7. return -EINVAL;
  8. }
  9. if (!desc->irq_data.chip) {
  10. printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
  11. return -EINVAL;
  12. }
  13. raw_spin_lock_irqsave(&desc->lock, flags);
  14. desc->irq_data.chip_data = data;
  15. raw_spin_unlock_irqrestore(&desc->lock, flags);
  16. return 0;
  17. }
  18. EXPORT_SYMBOL(set_irq_chip_data);

6.set_irq_data

[cpp] view plain copy

  1. int set_irq_data(unsigned int irq, void *data)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. unsigned long flags;
  5. if (!desc) {
  6. printk(KERN_ERR"Trying to install controller data for IRQ%d\n", irq);
  7. return -EINVAL;
  8. }
  9. raw_spin_lock_irqsave(&desc->lock, flags);
  10. desc->irq_data.handler_data = data;
  11. raw_spin_unlock_irqrestore(&desc->lock, flags);
  12. return 0;
  13. }
  14. EXPORT_SYMBOL(set_irq_data);

三、中断的申请与释放request_irq

1.申请中断(主要是分配设置irqaction结构体)

[cpp] view plain copy

  1. static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
  2. {
  3. return request_threaded_irq(irq, handler, NULL, flags, name, dev);
  4. }

1.1 request_threaded_irq函数

[cpp] view plain copy

  1. 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)
  2. {
  3. struct irqaction *action;
  4. struct irq_desc *desc;
  5. int retval;
  6. if ((irqflags & IRQF_SHARED) && !dev_id)    //共享中断但没指定中断id
  7. return -EINVAL;
  8. desc = irq_to_desc(irq);    //获取全局irq_desc数组项
  9. if (!desc)
  10. return -EINVAL;
  11. if (desc->status & IRQ_NOREQUEST)    //中断不能被请求
  12. return -EINVAL;
  13. if (!handler) { //没指定handler
  14. if (!thread_fn) //但存在thread_fn
  15. return -EINVAL;
  16. handler = irq_default_primary_handler;  //则设置irq_default_primary_handler
  17. }
  18. action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); //分配irqaction内存
  19. if (!action)
  20. return -ENOMEM;
  21. action->handler = handler;   //设置处理句柄
  22. action->thread_fn = thread_fn;   //设置线程函数NULL
  23. action->flags = irqflags;    //设置中断标志
  24. action->name = devname;      //设置设备名
  25. action->dev_id = dev_id; //设置设备id
  26. chip_bus_lock(desc);
  27. retval = __setup_irq(irq, desc, action);    //-->__setup_irq
  28. chip_bus_sync_unlock(desc);
  29. if (retval)
  30. kfree(action);
  31. #ifdef CONFIG_DEBUG_SHIRQ
  32. if (!retval && (irqflags & IRQF_SHARED)) {
  33. unsigned long flags;
  34. disable_irq(irq);
  35. local_irq_save(flags);
  36. handler(irq, dev_id);
  37. local_irq_restore(flags);
  38. enable_irq(irq);
  39. }
  40. #endif
  41. return retval;
  42. }
  43. EXPORT_SYMBOL(request_threaded_irq);

1.2 __setup_irq函数

[cpp] view plain copy

  1. static int __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
  2. {
  3. struct irqaction *old, **old_ptr;
  4. const char *old_name = NULL;
  5. unsigned long flags;
  6. int nested, shared = 0;
  7. int ret;
  8. if (!desc)
  9. return -EINVAL;
  10. if (desc->irq_data.chip == &no_irq_chip)
  11. return -ENOSYS;
  12. if (new->flags & IRQF_SAMPLE_RANDOM) {
  13. rand_initialize_irq(irq);
  14. }
  15. if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED))
  16. return -EINVAL;
  17. nested = desc->status & IRQ_NESTED_THREAD;   //嵌套标志
  18. if (nested) {   //嵌套
  19. if (!new->thread_fn) //且存在线程处理句柄
  20. return -EINVAL;
  21. new->handler = irq_nested_primary_handler;       //嵌套处理的句柄
  22. }
  23. if (new->thread_fn && !nested) { //非嵌套且存在线程函数
  24. struct task_struct *t;
  25. t = kthread_create(irq_thread, new, "irq/%d-%s", irq,new->name); //创建线程
  26. if (IS_ERR(t))
  27. return PTR_ERR(t);
  28. get_task_struct(t);
  29. new->thread = t; //设置线程任务结构体
  30. }
  31. raw_spin_lock_irqsave(&desc->lock, flags);
  32. old_ptr = &desc->action;
  33. old = *old_ptr;
  34. if (old) {
  35. if (!((old->flags & new->flags) & IRQF_SHARED) || ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
  36. old_name = old->name;
  37. goto mismatch;
  38. }
  39. #if defined(CONFIG_IRQ_PER_CPU)
  40. if ((old->flags & IRQF_PERCPU) != (new->flags & IRQF_PERCPU))
  41. goto mismatch;
  42. #endif
  43. do {
  44. old_ptr = &old->next;
  45. old = *old_ptr;
  46. } while (old);
  47. shared = 1; //共享中断标志
  48. }
  49. if (!shared) {  //非共享中断
  50. irq_chip_set_defaults(desc->irq_data.chip);      //设置默认的芯片处理函数
  51. init_waitqueue_head(&desc->wait_for_threads);
  52. if (new->flags & IRQF_TRIGGER_MASK) {    //设置触发方式
  53. ret = __irq_set_trigger(desc, irq,new->flags & IRQF_TRIGGER_MASK);
  54. if (ret)
  55. goto out_thread;
  56. }
  57. else
  58. compat_irq_chip_set_default_handler(desc);
  59. #if defined(CONFIG_IRQ_PER_CPU)
  60. if (new->flags & IRQF_PERCPU)
  61. desc->status |= IRQ_PER_CPU;
  62. #endif
  63. desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
  64. if (new->flags & IRQF_ONESHOT)
  65. desc->status |= IRQ_ONESHOT;
  66. if (!(desc->status & IRQ_NOAUTOEN)) {
  67. desc->depth = 0;
  68. desc->status &= ~IRQ_DISABLED;
  69. desc->irq_data.chip->irq_startup(&desc->irq_data);
  70. }
  71. else
  72. desc->depth = 1;
  73. if (new->flags & IRQF_NOBALANCING)
  74. desc->status |= IRQ_NO_BALANCING;
  75. setup_affinity(irq, desc);
  76. }
  77. else if ((new->flags & IRQF_TRIGGER_MASK)&& (new->flags & IRQF_TRIGGER_MASK)!= (desc->status & IRQ_TYPE_SENSE_MASK)) {
  78. pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
  79. irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),(int)(new->flags & IRQF_TRIGGER_MASK));
  80. }
  81. new->irq = irq;  //设置中断号
  82. *old_ptr = new;
  83. desc->irq_count = 0;
  84. desc->irqs_unhandled = 0;
  85. if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {  //共享中断
  86. desc->status &= ~IRQ_SPURIOUS_DISABLED;
  87. __enable_irq(desc, irq, false);
  88. }
  89. raw_spin_unlock_irqrestore(&desc->lock, flags);
  90. if (new->thread)
  91. wake_up_process(new->thread);
  92. register_irq_proc(irq, desc);   //注册proc irq接口
  93. new->dir = NULL;
  94. register_handler_proc(irq, new);    //注册proc handler接口
  95. return 0;
  96. mismatch:
  97. #ifdef CONFIG_DEBUG_SHIRQ
  98. if (!(new->flags & IRQF_PROBE_SHARED)) {
  99. printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
  100. if (old_name)
  101. printk(KERN_ERR "current handler: %s\n", old_name);
  102. dump_stack();
  103. }
  104. #endif
  105. ret = -EBUSY;
  106. out_thread:
  107. raw_spin_unlock_irqrestore(&desc->lock, flags);
  108. if (new->thread) {
  109. struct task_struct *t = new->thread;
  110. new->thread = NULL;
  111. if (likely(!test_bit(IRQTF_DIED, &new->thread_flags)))
  112. kthread_stop(t);
  113. put_task_struct(t);
  114. }
  115. return ret;
  116. }

代码可以去细究,主要功能是填充irqaction

在设备驱动程序中申请中断可以这么申请

(eg:request_irq(1, &XXX_interrupt,IRQF_TRIGGER_RISING,"nameXXX", (void*)0))

第一个参数是中断号,第二个参数是中断处理函数,第三个参数是中断标志(上升沿),第四个是名字,第五个是设备id(非共享中断设置成(void*)0)即可

共享中断情况下要将第三个参数添加IRQF_SHARED标志,同时要给他制定第五个参数设备id

触发方式宏

[cpp] view plain copy

  1. #define IRQ_TYPE_NONE       0x00000000  /* Default, unspecified type */
  2. #define IRQ_TYPE_EDGE_RISING    0x00000001  //上升沿触发
  3. #define IRQ_TYPE_EDGE_FALLING   0x00000002  //下降沿触发
  4. #define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)   //双边沿触发
  5. #define IRQ_TYPE_LEVEL_HIGH 0x00000004  //高电平有效
  6. #define IRQ_TYPE_LEVEL_LOW  0x00000008  //低电平有效
  7. #define IRQ_TYPE_SENSE_MASK 0x0000000f  /* Mask of the above */
  8. #define IRQ_TYPE_PROBE      0x00000010  /* Probing in progress */

然后设计中断函数

static irqreturn_t XXX_interrupt(int irq, void *arg){

......

return IRQ_HANDLED;

}

2.释放中断

[cpp] view plain copy

  1. void free_irq(unsigned int irq, void *dev_id)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. if (!desc)
  5. return;
  6. chip_bus_lock(desc);
  7. kfree(__free_irq(irq, dev_id));
  8. chip_bus_sync_unlock(desc);
  9. }
  10. EXPORT_SYMBOL(free_irq);

2.1 __free_irq

[cpp] view plain copy

  1. static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);   //获取全局irq_desc数组项
  4. struct irqaction *action, **action_ptr;
  5. unsigned long flags;
  6. WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
  7. if (!desc)
  8. return NULL;
  9. raw_spin_lock_irqsave(&desc->lock, flags);
  10. action_ptr = &desc->action;
  11. for (;;) {
  12. action = *action_ptr;
  13. if (!action) {
  14. WARN(1, "Trying to free already-free IRQ %d\n", irq);
  15. raw_spin_unlock_irqrestore(&desc->lock, flags);
  16. return NULL;
  17. }
  18. if (action->dev_id == dev_id)    //找到匹配的id项
  19. break;
  20. action_ptr = &action->next;
  21. }
  22. *action_ptr = action->next;
  23. #ifdef CONFIG_IRQ_RELEASE_METHOD
  24. if (desc->irq_data.chip->release)
  25. desc->irq_data.chip->release(irq, dev_id);
  26. #endif
  27. if (!desc->action) {
  28. desc->status |= IRQ_DISABLED;
  29. if (desc->irq_data.chip->irq_shutdown)
  30. desc->irq_data.chip->irq_shutdown(&desc->irq_data);
  31. else
  32. desc->irq_data.chip->irq_disable(&desc->irq_data);
  33. }
  34. #ifdef CONFIG_SMP
  35. if (WARN_ON_ONCE(desc->affinity_hint))
  36. desc->affinity_hint = NULL;
  37. #endif
  38. raw_spin_unlock_irqrestore(&desc->lock, flags);
  39. unregister_handler_proc(irq, action);
  40. synchronize_irq(irq);
  41. #ifdef CONFIG_DEBUG_SHIRQ
  42. if (action->flags & IRQF_SHARED) {
  43. local_irq_save(flags);
  44. action->handler(irq, dev_id);
  45. local_irq_restore(flags);
  46. }
  47. #endif
  48. if (action->thread) {
  49. if (!test_bit(IRQTF_DIED, &action->thread_flags))
  50. kthread_stop(action->thread);
  51. put_task_struct(action->thread);
  52. }
  53. return action;
  54. }

四、中断处理过程

1.当有中断发生时,程序会到__vectors_star去查找向量表(arch/arm/kernel/entry-armv.S)

[cpp] view plain copy

  1. .globl  __vectors_start
  2. _vectors_start:
  3. ARM(    swi SYS_ERROR0  )   /* swi指令 */
  4. THUMB(  svc #0      )
  5. THUMB(  nop         )
  6. W(b)    vector_und + stubs_offset
  7. W(ldr)  pc, .LCvswi + stubs_offset
  8. W(b)    vector_pabt + stubs_offset
  9. W(b)    vector_dabt + stubs_offset
  10. W(b)    vector_addrexcptn + stubs_offset
  11. W(b)    vector_irq + stubs_offset   /* 中断向量表 */
  12. W(b)    vector_fiq + stubs_offset
  13. .globl  __vectors_end
  14. _vectors_end:

2.vector_irq的定义声明

[cpp] view plain copy

  1. .globl  __stubs_start
  2. __stubs_start:
  3. /*
  4. * Interrupt dispatcher
  5. */
  6. vector_stub irq, IRQ_MODE, 4    /*参看下面vector_stub宏的定义*/
  7. .long   __irq_usr           @  0  (USR_26 / USR_32)     /*usr模式下中断处理(见下面)*/
  8. .long   __irq_invalid       @  1  (FIQ_26 / FIQ_32)
  9. .long   __irq_invalid       @  2  (IRQ_26 / IRQ_32)
  10. .long   __irq_svc           @  3  (SVC_26 / SVC_32)     /*svc模式下中断处理(见下面)*/
  11. .long   __irq_invalid       @  4
  12. .long   __irq_invalid       @  5
  13. .long   __irq_invalid       @  6
  14. .long   __irq_invalid       @  7
  15. .long   __irq_invalid       @  8
  16. .long   __irq_invalid       @  9
  17. .long   __irq_invalid       @  a
  18. .long   __irq_invalid       @  b
  19. .long   __irq_invalid       @  c
  20. .long   __irq_invalid       @  d
  21. .long   __irq_invalid       @  e
  22. .long   __irq_invalid       @  f

3.vector_stub宏的定义

[cpp] view plain copy

  1. /*vector_stub irq, IRQ_MODE, 4*/
  2. .macro  vector_stub, name, mode, correction=0
  3. .align  5
  4. vector_\name:                       /*构造了vector_irq*/
  5. .if \correction                 /*if 4*/
  6. sub lr, lr, #\correction
  7. .endif
  8. @
  9. @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
  10. @ (parent CPSR)
  11. @
  12. stmia   sp, {r0, lr}        @ save r0, lr
  13. mrs lr, spsr
  14. str lr, [sp, #8]        @ save spsr
  15. @
  16. @ Prepare for SVC32 mode.  IRQs remain disabled.    准备切到svc模式
  17. @
  18. mrs r0, cpsr
  19. eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
  20. msr spsr_cxsf, r0
  21. @ /*分支表必须紧接着这段代码*/
  22. @ the branch table must immediately follow this code
  23. @
  24. and lr, lr, #0x0f
  25. THUMB( adr r0, 1f          )
  26. THUMB( ldr lr, [r0, lr, lsl #2]    )
  27. mov r0, sp
  28. ARM(   ldr lr, [pc, lr, lsl #2]    )
  29. movs    pc, lr          @ branch to handler in SVC mode 跳到分支表处
  30. ENDPROC(vector_\name)
  31. .align  2
  32. @ handler addresses follow this label
  33. 1:
  34. .endm

这几段汇编的大致意思是中断发生会跳到vector_irq去执行,vector_irq根据情况会跳到__irq_usr或__irq_svc执行

4.__irq_usr

[cpp] view plain copy

  1. __irq_usr:
  2. usr_entry
  3. kuser_cmpxchg_check
  4. get_thread_info tsk
  5. #ifdef CONFIG_PREEMPT
  6. ldr r8, [tsk, #TI_PREEMPT]      @ get preempt count
  7. add r7, r8, #1          @ increment it
  8. str r7, [tsk, #TI_PREEMPT]
  9. #endif
  10. irq_handler     /*跳转到irq_handler处理*/
  11. #ifdef CONFIG_PREEMPT
  12. ldr r0, [tsk, #TI_PREEMPT]
  13. str r8, [tsk, #TI_PREEMPT]
  14. teq r0, r7
  15. ARM(   strne   r0, [r0, -r0]   )
  16. THUMB( movne   r0, #0      )
  17. THUMB( strne   r0, [r0]    )
  18. #endif
  19. mov why, #0
  20. b   ret_to_user
  21. UNWIND(.fnend      )
  22. ENDPROC(__irq_usr)

5.__irq_svc

[cpp] view plain copy

  1. __irq_svc:
  2. svc_entry
  3. #ifdef CONFIG_TRACE_IRQFLAGS
  4. bl  trace_hardirqs_off
  5. #endif
  6. #ifdef CONFIG_PREEMPT
  7. get_thread_info tsk
  8. ldr r8, [tsk, #TI_PREEMPT]      @ get preempt count
  9. add r7, r8, #1          @ increment it
  10. str r7, [tsk, #TI_PREEMPT]
  11. #endif
  12. irq_handler         /*跳转到irq_handler处理*/
  13. #ifdef CONFIG_PREEMPT
  14. str r8, [tsk, #TI_PREEMPT]      @ restore preempt count
  15. ldr r0, [tsk, #TI_FLAGS]        @ get flags
  16. teq r8, #0              @ if preempt count != 0
  17. movne   r0, #0              @ force flags to 0
  18. tst r0, #_TIF_NEED_RESCHED
  19. blne    svc_preempt
  20. #endif
  21. ldr r4, [sp, #S_PSR]        @ irqs are already disabled
  22. #ifdef CONFIG_TRACE_IRQFLAGS
  23. tst r4, #PSR_I_BIT
  24. bleq    trace_hardirqs_on
  25. #endif
  26. svc_exit r4             @ return from exception
  27. UNWIND(.fnend      )
  28. ENDPROC(__irq_svc)

6.不管是__irq_svc或是__irq_usr都会调用到irqhandler

[cpp] view plain copy

  1. .macro  irq_handler
  2. get_irqnr_preamble r5, lr
  3. 1:  get_irqnr_and_base r0, r6, r5, lr
  4. movne   r1, sp
  5. @ r0保存了中断号,r1保存了保留现场的寄存器指针
  6. @ routine called with r0 = irq number, r1 = struct pt_regs *
  7. @
  8. adrne   lr, BSYM(1b)
  9. bne asm_do_IRQ  /*********************跳转到asm_do_IRQ函数处理*/
  10. #ifdef CONFIG_SMP
  11. /*
  12. * XXX
  13. *
  14. * this macro assumes that irqstat (r6) and base (r5) are
  15. * preserved from get_irqnr_and_base above
  16. */
  17. ALT_SMP(test_for_ipi r0, r6, r5, lr)
  18. ALT_UP_B(9997f)
  19. movne   r0, sp
  20. adrne   lr, BSYM(1b)
  21. bne do_IPI
  22. #ifdef CONFIG_LOCAL_TIMERS
  23. test_for_ltirq r0, r6, r5, lr
  24. movne   r0, sp
  25. adrne   lr, BSYM(1b)
  26. bne do_local_timer
  27. #endif
  28. 9997:
  29. #endif
  30. .endm

7.就这样进入了c处理的阶段asm_do_IRQ

[cpp] view plain copy

  1. asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
  2. {
  3. struct pt_regs *old_regs = set_irq_regs(regs);
  4. irq_enter();
  5. /*
  6. * Some hardware gives randomly wrong interrupts.  Rather
  7. * than crashing, do something sensible.
  8. */
  9. if (unlikely(irq >= nr_irqs)) {  //中断号大于中断的个数
  10. if (printk_ratelimit())
  11. printk(KERN_WARNING "Bad IRQ%u\n", irq);
  12. ack_bad_irq(irq);
  13. }
  14. else {
  15. generic_handle_irq(irq);    //通用中断处理函数
  16. }
  17. /* AT91 specific workaround */
  18. irq_finish(irq);
  19. irq_exit();
  20. set_irq_regs(old_regs);
  21. }

8.generic_handle_irq函数

[cpp] view plain copy

  1. static inline void generic_handle_irq(unsigned int irq)
  2. {
  3. generic_handle_irq_desc(irq, irq_to_desc(irq)); //调用了irq_to_desc获取全局irq_desc[irq]项
  4. }

9.generic_handle_irq_desc函数

[cpp] view plain copy

  1. static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
  2. {
  3. #ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ   //根据板级配置的设置若定义了
  4. desc->handle_irq(irq, desc); //则只能用指定的handle_irq方法
  5. #else
  6. if (likely(desc->handle_irq))    //若中断处理函数存在
  7. desc->handle_irq(irq, desc); //则调用注册的中断处理函数(irq_desc[irq]->handle_irq(irq,desc))
  8. else
  9. __do_IRQ(irq);  //没指定中断处理函数的处理分支
  10. #endif
  11. }

这里有了分支关键看CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ的设置

如果设置为1,则只调用中断描述符的handle_irq方法

如果设置为0,则如果中断描述符存在handle_irq方法则调用该方法,如果没有则调用__do_IRQ()

中断描述符handle_irq方法,一般是芯片厂商写好的,先看看__do_IRQ()吧

10.__do_IRQ函数

[cpp] view plain copy

  1. unsigned int __do_IRQ(unsigned int irq)
  2. {
  3. struct irq_desc *desc = irq_to_desc(irq);
  4. struct irqaction *action;
  5. unsigned int status;
  6. kstat_incr_irqs_this_cpu(irq, desc);
  7. if (CHECK_IRQ_PER_CPU(desc->status)) {
  8. irqreturn_t action_ret;
  9. if (desc->irq_data.chip->ack)
  10. desc->irq_data.chip->ack(irq);
  11. if (likely(!(desc->status & IRQ_DISABLED))) {
  12. action_ret = handle_IRQ_event(irq, desc->action);//调用handle_IRQ_event函数
  13. if (!noirqdebug)
  14. note_interrupt(irq, desc, action_ret);
  15. }
  16. desc->irq_data.chip->end(irq);
  17. return 1;
  18. }
  19. raw_spin_lock(&desc->lock);
  20. if (desc->irq_data.chip->ack)
  21. desc->irq_data.chip->ack(irq);
  22. status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
  23. status |= IRQ_PENDING; /* we _want_ to handle it */
  24. action = NULL;
  25. if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
  26. action = desc->action;
  27. status &= ~IRQ_PENDING; /* we commit to handling */
  28. status |= IRQ_INPROGRESS; /* we are handling it */
  29. }
  30. desc->status = status;
  31. if (unlikely(!action))
  32. goto out;
  33. for (;;) {
  34. irqreturn_t action_ret;
  35. raw_spin_unlock(&desc->lock);
  36. action_ret = handle_IRQ_event(irq, action);//调用handle_IRQ_event函数
  37. if (!noirqdebug)
  38. note_interrupt(irq, desc, action_ret);
  39. raw_spin_lock(&desc->lock);
  40. if (likely(!(desc->status & IRQ_PENDING)))
  41. break;
  42. desc->status &= ~IRQ_PENDING;
  43. }
  44. desc->status &= ~IRQ_INPROGRESS;
  45. out:
  46. desc->irq_data.chip->end(irq);
  47. raw_spin_unlock(&desc->lock);
  48. return 1;
  49. }

.__do_IRQ函数主要是调用handle_IRQ_event来处理中断

11.handle_IRQ_event函数

[cpp] view plain copy

  1. irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
  2. {
  3. irqreturn_t ret, retval = IRQ_NONE;
  4. unsigned int status = 0;
  5. do {
  6. trace_irq_handler_entry(irq, action);
  7. ret = action->handler(irq, action->dev_id);//调用了irqaction的handler方法
  8. trace_irq_handler_exit(irq, action, ret);
  9. switch (ret) {
  10. case IRQ_WAKE_THREAD:
  11. ret = IRQ_HANDLED;
  12. if (unlikely(!action->thread_fn)) {
  13. warn_no_thread(irq, action);
  14. break;
  15. }
  16. if (likely(!test_bit(IRQTF_DIED,
  17. &action->thread_flags))) {
  18. set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
  19. wake_up_process(action->thread);
  20. }
  21. case IRQ_HANDLED:
  22. status |= action->flags;
  23. break;
  24. default:
  25. break;
  26. }
  27. retval |= ret;
  28. action = action->next;
  29. } while (action);
  30. if (status & IRQF_SAMPLE_RANDOM)
  31. add_interrupt_randomness(irq);
  32. local_irq_disable();
  33. return retval;
  34. }

这里调用的irqaction的handler方法就是调用了之前设备驱动中用request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)

申请中断时传递进来的第二个参数的函数
其实很多芯片厂商在编写中断描述符handle_irq方法的时候也会调用到handle_IRQ_event函数

整个中断的处理过程就是

时间: 2024-10-20 13:16:20

linux 中断机制浅析的相关文章

Linux 进程调度浅析

概述 操作系统要实现多进程,进程调度必不可少.有人说,进程调度是操作系统中最为重要的一个部分.我觉得这种说法说得太绝对了一点,就像很多人动辄就说"某某函数比某某函数效率高XX倍"一样,脱离了实际环境,这些结论是比较片面的. 而进程调度究竟有多重要呢? 首先,我们需要明确一点:进程调度是对 TASK_RUNNING 状态的进程进行调度.如果进程不可执行(正在睡眠或其他),那么它跟进程调度没多大关系.所以,如果你的系统负载非常低,盼星星盼月亮才出现一个可执行状态的进程.那么进程调度也就不会

linux 中断机制的处理过程

一.中断的概念 中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序.Linux中通常分为外部中断(又叫硬件中断)和内部中断(又叫异常). 在实地址模式中,CPU把内存中从0开始的1KB空间作为一个中断向量表.表中的每一项占4个字节.但是在保护模式中,有这4个字节的表项构成的中断向量表不满足实际需求,于是根据反映模式切换的信息和偏移量的足够使得中断向量

Linux 中断处理浅析

最近在研究异步消息处理, 突然想起linux内核的中断处理, 里面由始至终都贯穿着"重要的事马上做, 不重要的事推后做"的异步处理思想. 于是整理一下~ 第一阶段--获取中断号 每个CPU都有响应中断的能力, 每个CPU响应中断时都走相同的流程. 这个流程就是内核提供的中断服务程序. 在进入中断服务程序时, CPU已经自动禁止了本CPU上的中断响应, 因为CPU不能假定中断服务程序是可重入的. 中断处理程序的第一步要做两件事情: 1. 将中断号压入栈中; (不同中断号的中断对应不同的中

linux网桥浅析

转:http://www.cnblogs.com/morphling/p/3458546.html 什么是桥接? 简单来说,桥接就是把一台机器上的若干个网络接口"连接"起来.其结果是,其中一个网口收到的报文会被复制给其他网口并发送出去.以使得网口之间的报文能够互相转发.交换机就是这样一个设备,它有若干个网口,并且这些网口是桥接起来的.于是,与交换机相连的若干主机就能够通过交换机的报文转发而互相通信. 如下图:主机A发送的报文被送到交换机S1的eth0口,由于eth0与eth1.eth2

linux进程状态浅析

linux中的进程状态: ◆运行状态(TASK_RUNNING)(R状态) 指正在被CPU运行或者就绪的状态.这样的进程被成为runnning进程.运行态的进程可以分为3种情况:内核运行态.用户运行态.就绪态. 只有在该状态的进程才可能在CPU上运行.而同一时刻可能有多个进程处于可执行状态,这些进程的task_struct结构(进程控制块)被放入对应CPU的可执行队列中(一个进程最多只能出现在一个CPU的可执行队列中).进程调度器的任务就是从各个CPU的可执行队列中分别选择一个进程在该CPU上运

动静结合学内核之 linux 系统调用浅析

刘柳 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 直入主题 实验过程1-增加新的菜单 update the menu //git cone Uhange main.c //注册菜单函数 Add the chmodC ,chmodASM //菜单函数的实现 Make rootfs //激动人心的时刻,进入menuos调用我们新函数 chmodASM代码 讲述调用chmod系统调

Linux中断机制

1.中断概念 中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序.Linux中通常分为外部中断(又叫硬件中断)和内部中断(又叫异常). 在实地址模式中,CPU把内存中从0开始的1KB空间作为一个中断向量表.表中的每一项占4个字节.但是在保护模式中,有这4个字节的表项构成的中断向量表不满足实际需求,于是根据反映模式切换的信息和偏移量的足够使得中断向量表

linux 多任务浅析(二)

在一中我们说到了多任务即不同进程都有自己的独立的代码段,数据段,堆栈段.看似利用这个原理能将多任务隔离,但是他们各个段的起始地址又都是0,这就是很无语了,不过没关系,分页的时候会接着讲.这篇文章说一下多任务的切换. x86体系从硬件上支持任务间的切换,也就说实际上linux同一时间只是在运行一个任务,但是由于他可以在很短的时间在不同的任务间来回切换执行,我们感觉上他是多个任务一起执行的.既然要在任务间来回切换那么势必就要记录每一个进程被切换时的状态,以便切换回来的时候恢复.所有每一个进程都有属于

linux awk浅析(转)

Awk 是一种非常好的语言,同时有一个非常奇怪的名称.在本系列(共三篇文章)的第一篇文章中,Daniel Robbins 将使您迅速掌握 awk 编程技巧.随着本系列的进展,将讨论更高级的主题,最后将演示一个真正的高级 awk 演示程序. 捍卫 awk 在本系列文章中,我将使您成为精通 awk 的编码人员.我承认,awk 并没有一个非常好听且又非常“时髦”的名字.awk 的 GNU 版本(叫作 gawk)听起来非常怪异.那些不熟悉这种语言的人可能听说过 "awk",并可能认为它是一组落