Chinaunix首页 | 论坛 | 博客
  • 博客访问: 196246
  • 博文数量: 70
  • 博客积分: 26
  • 博客等级: 民兵
  • 技术积分: 1226
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-23 14:46
个人简介

linux --- 一切皆文件

文章分类

全部博文(70)

文章存档

2019年(2)

2018年(4)

2017年(7)

2016年(11)

2015年(1)

2014年(2)

2013年(33)

2012年(10)

分类: LINUX

2013-10-13 17:31:20

中断下班部有三种方法实现:
1:软中断
2:tasklet,tasklet软中断执行的一个链表,是由中断实现的
3:workqueue,工作队列是由内核线程实现的
总体来说,tasklet的效率比workqueue高,因为tasklet工作的中断上下文,但是不能有睡眠
而workqueue则是工作在进程上下文,可以存在睡眠操作。

1:软中断 一般不推荐使用
需要咋文件里添加信息:
enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
BLOCK_IOPOLL_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
KEY_SOFTIRQ, //自己添加的
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */


NR_SOFTIRQS
};
在这个枚举类型里添加信息。枚举一般是用来做数组的。


然后通过open_softirq(KEY_SOFTIRQ, softirq_handler);通过open_softirq()函数注册对应软中断的处理函数

在中断处理函数中raise_softirq(KEY_SOFTIRQ);raise_softirq()函数给这个软中断设置标志,当中断执行结束
马上去执行中断下半部。
网卡的收发包是直接在软中断中实现的,其他的可以在软中的tasklet,或者workqueue中实现。

2:tasklet,是软中断中的一种,让某个中断到来时就会唤醒tasklet_softirq,然后tasklet链表上的任务都会被执行,
tasklet工作在中断上下文中,不能有睡眠。

static DECLARE_TASKLET(my_tasklet, tasklet_handler, 0); 申请一个tasklet,挂在链表上
tasklet_schedule(&my_tasklet); 在中断处理函数设置下次在tasklet的时候进行调度

3:workqueue,是一个内核线程,工作在进程上下文,允许代码进行休眠,但是效率没有tasklet高
static DECLARE_WORK(my_work, work_handler); 创建一个工作任务
queue = create_workqueue("my_queue"); 创建一个工作队列

在中断处理函数中设置这个队列中这个任务可以执行,queue_work(queue, &my_work);

然后对出中断后的某个时间就会去执行这个queue上的任务


linux中使用grep搜索文件中的内容:    grep -rn '<\xxxxx' .


linux kernel 经典代码:
    这里使用的是免锁链表,首先将整个链表加锁,取下,然后解锁,这样的话以最短的时间解决的冲突,此时别人还能对tasklet_vec进行操作。
    然后取下来的链表操作的时候也不要
加锁,当如果取下来的链表中还有一些处理不了的任务,则就加锁重新放入到tasklet_vec这个链表上。这样就打打减少得了锁的时间

点击(此处)折叠或打开

  1. static void tasklet_action(struct softirq_action *a)
  2. {
  3.     struct tasklet_struct *list;

  4.     local_irq_disable();
  5.     list = __get_cpu_var(tasklet_vec).head;
  6.     __get_cpu_var(tasklet_vec).head = NULL;
  7.     __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
  8.     local_irq_enable();

  9.     while (list) {
  10.         struct tasklet_struct *t = list;

  11.         list = list->next;

  12.         if (tasklet_trylock(t)) {
  13.             if (!atomic_read(&t->count)) {
  14.                 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
  15.                     BUG();
  16.                 t->func(t->data);
  17.                 tasklet_unlock(t);
  18.                 continue;
  19.             }
  20.             tasklet_unlock(t);
  21.         }

  22.         local_irq_disable();
  23.         t->next = NULL;
  24.         *__get_cpu_var(tasklet_vec).tail = t;
  25.         __get_cpu_var(tasklet_vec).tail = &(t->next);
  26.         __raise_softirq_irqoff(TASKLET_SOFTIRQ);
  27.         local_irq_enable();
  28.     }
  29. }


阅读(1347) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册