九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 5666|回复: 1

x4412&ibox项目实战44-Linux中断编程实验(四)

[复制链接]
发表于 2014-10-14 13:52:39 | 显示全部楼层 |阅读模式
使用软中断也可以实现中断编程。使用Linux底半部机制存在以下两大缺点:
一:在任意时刻,系统中只能有一个CPU可以执行底半部的代码,以防止两个或多个CPU同时来执行底半部代码而相互干扰;因此,底半部代码的执行必须是严格"串行化"的;
二:底半部函数不允许嵌套。
这两个缺点在单CPU系统中是无关紧要的,但是在SMP系统中却是非常致命的。因为,底半部机制的严格串行化执行显然没有充分利用SMP系统的多CPU特点。为此,Linux内核在底半部机制的基础上进行了扩展,那就是所谓的"软中断"(softirq)机制。
Linux的软中断机制是与SMP紧密联系而不可分的。为此,整个软中断机制的设计与实现,自始至终都贯彻了一个思想:“谁触发,谁执行”。也就是说,触发中断的那个CPU负责执行它所触发的软中断,而且,每个CPU都有自己的软中断触发与控制机制。这个设计思想也使得软中断机制充分利用了SMP系统的性能和特点。
软中断运行于中断上下文,它所调用的函数都是内核函数,因此使用软中断机制的驱动不允许编译成模块,只能编译进内核。
使用软中断机制编写驱动程序,实现在串口终端定时打印一条语句。
在kernel/drivers/char/x4412目录下新建驱动程序x4412-softirq.c文件,编辑内容如下:
  1. #include <linux/module.h>
  2. #include <linux/version.h>
  3. #include <linux/init.h>
  4. #include <linux/kernel.h>
  5. #include <linux/jiffies.h>
  6. #include <linux/delay.h>
  7. #include <linux/sched.h>
  8. #include <linux/kthread.h>
  9. #include <linux/err.h>
  10. #include <linux/interrupt.h>
  11. //STEP1:在linux/interrupt.h中自定义软中断索引X4412_SOFTIRQ
  12. static int flag = 0;
  13. //STEP2:实现软中断处理函数;
  14. void x4412_ibox_softirq(struct softirq_action* sa)
  15. {
  16.          flag = 1;
  17.          printk("%s. \n", __FUNCTION__);
  18. }
  19. static int thread_process(void* param)
  20. {
  21.          while(1)
  22.          {
  23.                    set_current_state(TASK_UNINTERRUPTIBLE);
  24.                    if(kthread_should_stop())
  25.                    {
  26.                             printk("kernel thread should stop;file:%s;line:%d\n", __FILE__, __LINE__);
  27.                             break;
  28.                    }
  29.                    mdelay(10*HZ);
  30.                    if(0 == flag)
  31.                    {
  32.                             raise_softirq(X4412_SOFTIRQ); //STEP4:触发软中断;
  33.                    }
  34.                    else
  35.                    {
  36.                             flag = 0;
  37.                    }
  38.          }
  39.          return 1;
  40. }
  41. static struct task_struct* x4412_thread = NULL;
  42. static int __init x4412_softirq_init(void)
  43. {
  44.          int err = 0;
  45.          printk("%s\n", __PRETTY_FUNCTION__);
  46.          open_softirq(X4412_SOFTIRQ, x4412_ibox_softirq); //STEP3:注册软中断
  47.          x4412_thread = kthread_create(thread_process, NULL, "x4412_thread");
  48.          if(IS_ERR(x4412_thread))
  49.          {
  50.                    err = PTR_ERR(x4412_thread);
  51.                    x4412_thread = NULL;
  52.                    printk(KERN_ERR "unable to start kernel thread:%d\n", err);
  53.                    return err;
  54.          }
  55.          wake_up_process(x4412_thread);
  56.          printk("x4412 kernel thread start;file:%s;line:%d\n", __FILE__, __LINE__);
  57.          return 0;
  58. }
  59. static void __exit x4412_softirq_exit(void)
  60. {
  61.          int ret = -1;
  62.          if(x4412_thread)
  63.          {
  64.                    ret = kthread_stop(x4412_thread);
  65.                    x4412_thread = NULL;
  66.          }
  67.          printk("kernel thread stop,exit code is %d;file:%s;line:%d\n",ret, __FILE__, __LINE__);
  68. }
  69. MODULE_LICENSE("GPL");
  70. MODULE_AUTHOR("www.9tripod.com");
  71. module_init(x4412_softirq_init);
  72. module_exit(x4412_softirq_exit);
复制代码
       linux/interrupt.h中添加自定义的中断号:
  1. enum
  2. {
  3.          HI_SOFTIRQ=0,
  4.          TIMER_SOFTIRQ,
  5.          NET_TX_SOFTIRQ,
  6.          NET_RX_SOFTIRQ,
  7.          BLOCK_SOFTIRQ,
  8.          BLOCK_IOPOLL_SOFTIRQ,
  9.          TASKLET_SOFTIRQ,
  10.          SCHED_SOFTIRQ,
  11.          HRTIMER_SOFTIRQ,
  12.          X4412_SOFTIRQ,   /*自定义的中断*/
  13.          RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

  14.          NR_SOFTIRQS
  15. };
复制代码
       编辑kernel/drivers/char/x4412/Kconfig文件,添加内容如下:
  1. config X4412_SOFTIRQ_DRIVER
  2.          tristate "x4412 softirq driver"
  3.          default y
  4.          help
  5.          compile for x4412 softirq driver,y for kernel,no for dismod.
复制代码
       编辑kernel/drivers/char/x4412/Makefile文件,添加内容如下:
  1. obj-$(CONFIG_X4412_SOFTIRQ_DRIVER) += x4412-softirq.o
复制代码
       编译内核,在kernel/drivers/char/x4412目录下将会生成x4412-softirq.o文件,同时它将会被打包到内核映像zImage中。更新开发板的内核,观察系统启动后串口终端的打印信息。
  1. [root@x4412 ~]#
  2. [   23.945014] x4412_ibox_softirq.
  3. [   27.940013] x4412_ibox_softirq.
  4. [   31.940013] x4412_ibox_softirq.
  5. [   35.940013] x4412_ibox_softirq.
复制代码
       可见,每隔约4秒将会打印一次信息。
       结合源码,可以得出软中断的编程步骤。
       第一步:在linux/interrupt.h中添加自定义的中断号:
  1. enum
  2. {
  3.          HI_SOFTIRQ=0,
  4.   ……
  5.          X4412_SOFTIRQ,
  6.          RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

  7.          NR_SOFTIRQS
  8. };
复制代码
       第二步:实现软中断处理函数:
  1. void x4412_ibox_softirq(struct softirq_action* sa)
  2. {
  3.          ……
  4. };
复制代码
       第三步:在驱动初始化函数或open函数中注册软中断:
  1. open_softirq(X4412_SOFTIRQ, x4412_ibox_softirq);
复制代码
       这里第一个参数对应前面我们自定义的软中断号,第二个参数为中断处理函数名。
       第四步:触发软中断:
  1. raise_softirq(X4412_SOFTIRQ);
复制代码
       同样,形式参数仍然是自定义的软中断号。

编译好的内核映像:
zImage.part1.rar (1.9 MB, 下载次数: 8)
回复

使用道具 举报

发表于 2017-2-14 23:13:03 | 显示全部楼层
项目实战里面居然没有线程讲解,这一章刚好出现了线程
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-3-29 15:30 , Processed in 0.022240 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表