Linux内核中断和异常分析(中)

在linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线。所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,上次讲到单片机的时候,我就讲到了单片机中断的一些概念。我们现在来看一幅图,更好说明一个问题:

     这下面的这幅图是51单片机的一个关于矩阵键盘的学习的一个proteus的仿真电路图。

其中P3.2和P3.3为外部中断引脚,当可编程控制器(51MCU)收到外部中断响应的时候,会执行一些特定的操作,当然这需要开发者去编写一个中断初始化程序和一个中断服务程序。

那么,可编程中断控制器会做以下的操作:

1、监视IRQ线,我们可以理解就是监视单片机外部中断的IO口,检查产生的信号。如果有条或者两条以上的IRQ上产生信号,就选择引脚编号较小的IRQ线。

2、如果一个引发信号出现在IRQ线上:

   a.把接收到的引发信号转换成对应的向量。

   b.把这个向量存放在中断控制器的一个I/O端口,从而允许CPU通过数据总线读这个向量。

   c.把引发信号发送到处理器的INTR引脚,即会产生一个中断。

   d.等待,直到CPU通过把这个中断信号写进可编程中断控制器的一个I/O端口来确认它,当这种情况发送时,清INTR线。

3、最后一步返回到第一步继续监视,然后依次执行。

    当然,也存在着一些更加高级的可编程中断控制器,其中ARM算一种,Intel也是,等等。。。单片机算是最简单的一种。像多APIC系统的结构,会存在以下的一个图的关系:

中断信号通过IO引脚,然后通过中断控制器I2C总线与相应的CPU进行通信。

一般情况下,有两种分发的方式:

1、静态分发模式:IRQ信号传递给重定向表相应的项中所列出的本地APIC,然后中断立即传递诶一个特定的CPU,或者是一组CPU,或者是所有的CPU。其实这是广播模式的一种模型,接触过UNIX网络编程应该会知道。

2、动态分发模式:如果处理器正在执行最低优先级的进程,IRQ信号线就会传递给这种处理器的本地APIC。也就是说,在CPU内部有一个控制优先级的寄存器,用来计算当前运行进程的优先级。如果两个或者多个CPU共享最低优先级,那么就利用仲裁的技术在这些CPU之间分配负荷等等的形式。

上篇文章曾介绍异常的相关,异常有很多种,在8086处理器可以找到多达20种不同的异常,内核必须为每种异常提供一个专门的异常处理程序。对于某些异常,CPU控制单元会在开始执行异常处理程序前产生一个硬件出错码,并且压入内核态的堆栈中去。

     关于这个异常处理信息,我们有必要来了解以下perror这个函数。

perror( ) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno(这里的说法不准确,errno是一个宏,该宏返回左值) 的值来决定要输出的字符串。在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

用法:void perror(const char *s); perror ("open_port");

我们写段代码来看看就知道了:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *filp ;
	filp = fopen("txt","r");
	if(NULL == filp)
	{
		perror("没有相应的文件");
	}
	return 0 ;
}

运行结果:

在当前目录下,找不到txt这个文件,所以perror会根据相应的出错信息打印No such file or directory。


看了这个函数的应用,相信更会理解上面的异常的相关知识。当然还有更多的,比如段错误,段错误是最常见的,一些初学者在使用指针的时候,没有分配相应的空间,这时候给指针赋值,虽然没有语法错误,但可能会有警告。当程序运行的时候,就会自动退出并提示段错误(Segment fault),这一般是在linux上会出现这两个英语单词,在window的Devcpp上是这样,:

     段错误的产生原因有很多种,程序在进行递归的时候,如果没有相应的条件退出的话,程序一旦进行死循环递归之后就会产生爆栈错误,也就是栈被挤爆了,栈这个概念其实并不陌生。我们在写C语言程序的时候,一旦写了一个子函数,那就相当于建立了一个堆栈,一般情况下函数在执行完退出后堆栈是自动分配,自动销毁的,不用程序员去手动malloc申请内存再free释放内存。因为手动分配的内存是用了堆区的内存,而自动分配是在栈区进行分配的。在32位操作系统上,栈的大小就只有12M,所以写代码的时候,一定要记得防止爆栈错误的产生,特别是递归!在main函数中多写些子函数是有好处的,要养成良好的编程习惯。

     接下来的一篇,我将结合相应的内核驱动的代码实例来剖析linux内核中断与异常来作为文章的终结。欢迎持续关注Bruce.yang的嵌入式之旅!

  

时间: 2024-08-30 09:06:23

Linux内核中断和异常分析(中)的相关文章

Linux内核中断和异常分析(上)

中断,通常被定义为一个事件.打个比方,你烧热水,水沸腾了,这时候你要去关掉烧热水的电磁炉,然后再去办之前手中停不下来的事情.那么热水沸腾就是打断你正常工作的一个信号机制.当然,还有其它的情况,我们以后再做分析.       中断也就是这样产生的,中断分为同步中断还有异步中断.       同步中断在Intel的手册中被称为异常,而异步中断被称作中断.打个比方在ARM处理器的异常种类就有不少,有未定义指令异常,软中断异常,快中断异常等等.异常是由程序错误产生的,或者是内核必须处理的异常条件产生的.

Linux内核中断和异常分析(下)

这节,我们继续上,中(以前的日志有)篇目进行分析,结合一个真实的驱动案例来描述linux内核中驱动的中断机制,首先我们先了解一下linux内核中提供的中断接口.      这个接口我们需要包含一个头文件:#include <linux/interrupt.h>      在中断接口中,最重要的是以下的接口函数: 1.这个是请求中断函数 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags,

Linux的中断和异常扫盲笔记

广义的中断: 什么是中断: 所谓中断是指CPU对系统发生的某个事件作出的一种反应,让CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程:CPU在遇到某个事件时,暂停正在执行的程序,保留现场后自动地转去执行相应的处理程序,处理完该事件后再返回断点继续执行被"打断"的程序.事实上CPU对于中断和异常的具体处理机制本质上是完全一致的 即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断. 广义的中断包含异

Linux内核抢占实现机制分析【转】

Linux内核抢占实现机制分析  转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介绍了内核抢占和用户抢占的概念和区别,接着分析了不可抢占内核的特点及实时系统中实现内核抢占的必要性.然后分析了禁止内核抢占的情况和内核抢占的时机,最后介绍了实现抢占内核所做的改动以及何时需要重新调度.   [关键字]内核抢占,用户抢占,中断, 实时性,自旋锁,抢占时机,调度时机,schedule,p

Linux 内核中断内幕【转】

转自:https://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器.中断分类.中断亲和力.中断线程化与 SMP 中的中断迁徙等.首先对中断工作原理进行了简要分析,接着详细探讨了中断亲和力的实现原理,最后对中断线程化与非线程化中断之间的实现机理进行了对比分析. 3评论 苏 春艳, 在读研究生 杨 小华 (normalnotebook@126.com),

【内核】linux内核启动流程详细分析【转】

转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程  arch/arm/kernel/head-armv.S  该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用是检查CPU ID, Architecture Type,初始化BSS等操作,并跳到start_kernel函数.在执行前,处理器应满足以下状态:  r0 - should be 0 r1 - unique

Linux内核协议栈-初始化流程分析

本文主要针对Linux-3.19.3版本的内核简单分析内核协议栈初始化涉及到的主要步骤和关键函数,不针对协议的解析以及数据包的处理流程做具体分析,后续有机会再详细分析 1.准备 Linux内核协议栈本身构建在虚拟文件系统之上,所以对Linux VFS不太了解的可以参考内核源码根目录下Documentation/filesystems/vfs.txt,另外,socket接口层,协议层,设备层的许多数据结构涉及到内存管理,所以对基本虚拟内存管理,slab缓存,页高速缓存不太了解的也可以查阅相关文档.

Linux内核态抢占机制分析

本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核(Preemptive Kernel)的区别.接着分析Linux下有两种抢占:用户态抢占(User Preemption).内核态抢占(Kernel Preemption).然后分析了在内核态下:如何判断能否抢占内核(什么是可抢占的条件);何时触发重新调度(何时设置可抢占条件);抢占发生的时机(何时检查可抢占的条件);什么时候不能抢占内核.最后分析了2.6kernel中如何支持抢占内核. 1. 非抢占式和可抢占式

Linux内核中断引入用户空间(异步通知机制)【转】

转自:http://blog.csdn.net/kingdragonfly120/article/details/10858647 版权声明:本文为博主原创文章,未经博主允许不得转载.         当Linux内核空间发生中断后怎么使用户空间的应用程序运行相应的函数呢,当芯片有数据到来时内核会产生一个中断,但是怎样通知应用程序来取数据,以前这个问题一直困扰我很长时间,后来发现linux中有异步通知机制,在用户程序中用signal注册一个响应SIGIO信号的回调函数,然后在驱动程序中向该进程发