内核线程软中断和定时器有何区别

Posted xjbclz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核线程软中断和定时器有何区别相关的知识,希望对你有一定的参考价值。

内核线程、软中断和定时器有何区别?

在慢速中断的过程中,允许别的中断发生

 

 
 Re: 内核线程、软中断和定时器有何区别?

2.4中还有慢速中断吗? 

 

 
 Re: 内核线程、软中断和定时器有何区别?

有,其实就是软中断. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

你好快,就成newbie了,我努力了好几个月才成newbie 

慢速中断不应该是软中断吧?如果说慢速中断是可以中断的中断,那应该是那种没有XX_INTERRUPT标志的中断,系统响应时会打开中断。 

软中断应该就是tasklet 


 

 
 Re: 内核线程、软中断和定时器有何区别?

我觉得首先讲一下LINUX的内核机制: 
传统的UNIX把内核分成两部分:TOP HALF和BOTTOMHALF.BOTTOM呢是由异步事件来调用的,其实在LINUX中不严格的说就是中断.TOP是由系统调用来调用的.注意这里的 BOTTOM HALF和LINUX2.2中的并在LINUX2.4也支持的BH机制不是一回事情. 
好了,现在讲你问的问题: 
软中断其实就是把一个异步事件的响应分成两个部分的一个部分.另一个叫硬中断.硬中断必须实时响应,软中断可以等有时间再做,LINUX怎么调度软中断,有三个途径,从系统掉用,异常和中断中返回的时候有检查要不要执行软终端. 
对于一个时钟,很显然时钟中断的服务程序也被分成两个部分,一个就是硬中断,一个就是软中断了.你说的定时器我估计就是指时钟中断的软中断. 
对与内核线程,LINUX从2.4的一些高端版本好象也开始采用了对某些软中断使用这中方法,即把软中断作为一个线程来执行. 


 

 
 Re: 内核线程、软中断和定时器有何区别?

从他的意思来看就是软中断. 
我原来比NEWBIE的级别还高一点呢,现在我换名字了. 
你说的TASKLET只是软中断的一种类型. 
对于中断的服务程序的设计,要具体对待,对于服务程序不大,没有必要采用软中断机制.直接关中断就可以了.你说的对XXX_INTERUPT如果象你那么设计,就不是采用软中断的机制了,在早期的UNIX是这么实现的,即一个中断服务不分成两个部分,只是在服务程序中开哪些中断.譬如 XENIX2.3.4就是这么设计的.至于LINUX可以不可以也这么直接写服务程序,我不知道.不过通常都是软硬中断分开的. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

我想你没有理解他的意思。他说的慢速中断是指没有SA_INTERRUPT标志的中断。 

以下是相关代码: 
 

int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)



	int status;

	int cpu = smp_processor_id();



	irq_enter(cpu, irq);



	status = 1;	/* Force the "do bottom halves" bit */



	/*慢速中断则开中断*/

	if (!(action->flags & SA_INTERRUPT))

		__sti();

	do 

		status |= action->flags;

		action->handler(irq, action->dev_id, regs);

		action = action->next;

	 while (action);

	if (status & SA_SAMPLE_RANDOM)

		add_interrupt_randomness(irq);

	__cli();



	irq_exit(cpu, irq);



	return status;







 
 
 Re: 内核线程、软中断和定时器有何区别?

我觉得这个好象包括在软中断的机制里面吧? 

 

 
 Re: 内核线程、软中断和定时器有何区别?

你这里采用的就是软中断的机制之一的BH机制. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

有没搞错?handle_IRQ_event()是IRQ!是硬中断! 

 

 
 Re: 内核线程、软中断和定时器有何区别?

wheelz说得对,我说的慢速中断就是慢速中断,不是软中断 
软中断的处理函数是do_softirq(),在kernel/softirq.c文件中 

 

 
 Re: 内核线程、软中断和定时器有何区别?

>你这里采用的就是软中断的机制之一的BH机制. 

这是硬中断,不是BH机制: 
action->handler(irq, action->dev_id, regs); 
BH机制的函数是无参数无返回的:) 

 

 
 Re: 内核线程、软中断和定时器有何区别?

你只知道其一,不知道其二,作为优化,软中断未必就必须那么执行,在没有其他硬中断的时候,就直接执行算了,你以为DO_IRQ里面的检查是做什么的呀?首先把ACTION=NULL的那一段的代码, 

 

 
 Re: 内核线程、软中断和定时器有何区别?

在执行硬中断的时候,如果没有检测到其他的高级中断,直接执行他的软中断算了.因此,从概念上说,他是属于软中断的,尽管他同硬中断一道执行的. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

没有搞错,你假设一在他里面发生了高级的中断,他怎么处理?假设这个中断发生在其他的低级中断中,他怎么处理?还能执行到这个 IRQ_HANLDLER_EVENT么?不能,只能作为软中断执行了.这里做为优化,在没有检测到其他高级的中断的时候,直接就在硬中断后面把软中断执行掉了算了,从实际来讲,他是在硬中断之后执行的,但从概念上,他是属于软中断的范畴. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

你仔细看一ULK2的4.6和4.7节,看看hande_IRQ_event 是不是书上所讲的deferrable function的涵义. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

我都懒得跟你争,你居然认为handle_IRQ_event()是软中断? 


 

 
 Re: 内核线程、软中断和定时器有何区别?

书上所讲的deferrable function指的是bottom half和tasklet,它们是由do_softirq调用的,而不是hande_IRQ_event. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

好,既然有处理软中断的例程,那么我问:软中断在哪里产生的?也就是说,在什么地方,硬中断把软中断挂入队列?你只能在DO_IRQ中找. 
从整个中断发生的流程来看,先是从IRQXXX_INTERUPT跳到COMMON_INTERUPPT,直到调用DO_IRQ,根据软中断的定义我们可以知道,他必须由硬中断产生,并挂入软中断处理队列,请问,这个处理动作在哪里产生的? 

 

 
 Re: 内核线程、软中断和定时器有何区别?

硬中断只产生中断请求队列,我确实不知道,硬中断还要处理中断请求.按照你的理解,第一个中断产生了一个handle_IRQ_event1中产生了一个中断2,它应该包含一个handle_IRQ_event2,只要没有被别的中断打断的话,就该执行完,那不就是event2在event1中执行了么? 你没有办法确定event2和event1是不是一个中断,假设是一个中断呢?你就必须考虑你的中断程序的可重入的问题.这无疑增加了驱动程序开发的难度. 
另外,你说我错了没有什么关系,我错了,但是我可以说说我为什么有这么错误理解的理由,"懒得同我辩",搞得我好象是故意捣乱似的. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

我想问题已经很清楚了,这只是一个概念上的问题,并没有谁对谁错,在争下去也没有什么意义,我觉得我或者freshground或者wheelz是不会被你说服的,你觉得你会被我们说服吗?:) 
这里我们称呼你所说的软中断为慢速中断是因为 
1.ldd2上是这么写的,我们也就这么称呼了 
2.如果我们称慢速中断为软中断,那就会把开中断执行的硬中断(当然,你称它为软中断)和softirq搞混 

希望大家不要为了一个概念的问题伤了和气,这好像太不值得了 

 

 
 Re: 内核线程、软中断和定时器有何区别?

呵呵,“懒得和你争”其实是我调侃的气话,我愿意向你道歉:-)。 

下面我就你在两个讨论话题中的问题和你探讨。我觉得你对中断部分的理解是错误的, 
具体说就是你没有仔细看do_IRQ() 


>>硬中断只产生中断请求队列,我确实不知道,硬中断还要处理中断请求. 
按照你的理解,第一个中断产生了一个handle_IRQ_event1中产生了一个中断2, 
它应该包含一个handle_IRQ_event2,只要没有被别的中断打断的话,就该执行完, 
那不就是event2在event1中执行了么? 你没有办法确定event2和event1是不是一个中断, 
假设是一个中断呢?你就必须考虑你的中断程序的可重入的问题. 
这无疑增加了驱动程序开发的难度. 


没错,在这种情况下,event2是在event1中执行! 
并且,event2和event1不可能是同一个中断, 
do_IRQ()保证了这一点,因为,如果同一个中断第二次发生,其相应desc->status有 
IRQ_INPROGRESS标志,这样局部变量action==NULL,不会得到赋值, 
因此goto out;同时,desc->status会并上IRQ_PENDING标志,这样, 
当上一次中断响应完成后(for循环中,handle_IRQ_event之后), 
会检查IRQ_PENDING标志,因而再循环一次 
再次处理本中断, 
这样也解决了重入的问题。 



>>我觉得从开中断哪里讨论是不合适的,而是从DO_IRQ这个涵数开始, 
在该书的P215页的注释607-617行,这一段代码,一定要执行到么? 
如果回答是否定的,即有可能执行到也有可能不执行到,而是延时执行, 
那么延时到哪里执行?一个就是FOR循环,一个就DO_SOFTIRQ了, 
用ULK2的话说就是DEFFERABLE FUNCTION了,从这个意义上讲, 
不就是软中断了么? 


这段代码是一定要执行的,只有在action==NULL的情况下才会goto out; 
那么什么情况下action会等于NULL呢?只有IRQ_DISABLED和IRQ_INPROGRESS, 
也就是说只有当前中断被禁止或正在处理的情况下该循环 
才不会执行。 


下面是do_IRQ()的代码,取自2.4.20 

 

/*

 * do_IRQ handles all normal device IRQ's (the special

 * SMP cross-CPU interrupts have their own specific

 * handlers).

 */

asmlinkage unsigned int do_IRQ(struct pt_regs regs)

	

	/* 

	 * We ack quickly, we don't want the irq controller

	 * thinking we're snobs just because some other CPU has

	 * disabled global interrupts (we have already done the

	 * INT_ACK cycles, it's too late to try to pretend to the

	 * controller that we aren't taking the interrupt).

	 *

	 * 0 return value means that this irq is already being

	 * handled by some other CPU. (or is disabled)

	 */

	int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */

	int cpu = smp_processor_id();

	irq_desc_t *desc = irq_desc + irq;

	struct irqaction * action;

	unsigned int status;

#ifdef CONFIG_DEBUG_STACKOVERFLOW

	long esp;



	/* Debugging check for stack overflow: is there less than 1KB free? */

	__asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));

	if (unlikely(esp < (sizeof(struct task_struct) + 1024))) 

		extern void show_stack(unsigned long *);



		printk("do_IRQ: stack overflow: %ld\\n",

			esp - sizeof(struct task_struct));

		__asm__ __volatile__("movl %%esp,%0" : "=r" (esp));

		show_stack((void *)esp);

	

#endif



	kstat.irqs[cpu][irq]++;

	spin_lock(&desc->lock);

	desc->handler->ack(irq);

	/*

	   REPLAY is when Linux resends an IRQ that was dropped earlier

	   WAITING is used by probe to mark irqs that are being tested

	   */

	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);

	status |= IRQ_PENDING; /* we _want_ to handle it */



	/*

	 * If the IRQ is disabled for whatever reason, we cannot

	 * use the action we have.

	 */

	action = NULL;

	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) 

		action = desc->action;

		status &= ~IRQ_PENDING; /* we commit to handling */

		status |= IRQ_INPROGRESS; /* we are handling it */

	

	desc->status = status;



	/*

	 * If there is no IRQ handler or it was disabled, exit early.

	   Since we set PENDING, if another processor is handling

	   a different instance of this same irq, the other processor

	   will take care of it.

	 */

	if (!action)

		goto out;



	/*

	 * Edge triggered interrupts need to remember

	 * pending events.

	 * This applies to any hw interrupts that allow a second

	 * instance of the same irq to arrive while we are in do_IRQ

	 * or in the handler. But the code here _disibledevent="darktable" valign="top" width="2%" rowspan="2">
Re: 内核线程、软中断和定时器有何区别?

"呵呵,“懒得和你争”其实是我调侃的气话,我愿意向你道歉:-)。" 
嘻嘻,那么认真干嘛?我从来就喜欢胡思乱想,胡言乱语,只要你不生气就好了.这么郑重的
道歉显得我太小气了哦. 

 

 
 Re: 内核线程、软中断和定时器有何区别?

我觉得还是你们的有道理,在我仔细对照了ULK2和LDD2等资料之后,只是碰巧我找到了别人的学习笔记,理解的同我差不多,哈哈,也犯了和我一样的错误,转贴如下(太长了,只搞连接): 
http://joyfire.net/jln/kernel/2.html#I367 

以上是关于内核线程软中断和定时器有何区别的主要内容,如果未能解决你的问题,请参考以下文章

Linux并发与同步专题

#导入Word文档图片# Linux下内核微线程tasklet

Linux内核定时器

软中断的概念

Linux x86_64内核中断初始化

《深入理解Linux内核》软中断/tasklet/工作队列