软中断:
编程异常通常叫做软中断
软中断是通讯进程之间用来模拟硬中断的 一种信号通讯方式。
中断源发中断请求或软中断信号后,CPU或接收进程在适当的时机自动进行中断处理或完成软中断信号对应的功能
软中断是软件实现的中断,也就是程序运行时其他程序对它的中断;而硬中断是硬件实现的中断,是程序运行时设备对它的中断。
1.软中断发生的时间是由程序控制的,而硬中断发生的时间是随机的
2.软中断是由程序调用发生的,而硬中断是由外设引发的
3.硬件中断处理程序要确保它能快速地完成它的任务,这样程序执行时才不会等待较长时间
对于一般的C语言爱好者而言,就如何在C中使用中断例程这一问题应该已经非常熟悉,例如,我们可以通过int86 ( )函数调用13H号中断直接对磁盘物理扇区进行操作,也可以通过INT86 ( )函数调用33H号中断在屏幕上显示鼠标光标等。其实,13H号也好,33H号也好,它们只不过就是一些函数,这些函数的参数通过CPU的寄存器传递。中断号也只不过是间接地指向函数体的起始内存单元,说它是间接的,也就是说,函数的起始段地址和偏移量是由中断号通过一种方法算得的(具体如何操作,下面会作解释)。如此一来,程序员不必要用太多的时间去写操作硬件的程序了,只要在自己的程序中设置好参数,再调用BIOS或DOS提供的中断服务程序就可以了,大大减小了程序开发难度,缩短了程序开发周期。那么中断既然是函数,就可以由用户任意的调用、由用户任意地编写。
计算机内存的前1024个字节(偏移量00000H到003FFH)保存着256个中断向量,每个中断向量占4个字节,前两个字节保存着中断服务程序的入口地址偏移量,后两个字节保存着中断程序的入口段地址,使用时,只要将它们分别调入寄存器IP及CS中,就可以转入中断服务程序实现中断调用。每当中断发生时,CPU将中断号乘以4,在中断向量表中得到该中断向量地址,进而获得IP及CS值,从而转到中断服务程序的入口地址,调用中断。这就是中断服务程序通过中断号调用的基本过程。在计算机启动的时候,BIOS将基本的中断填入中断向量表,当DOS得到系统控制权后,它又要将一些中断向量填入表中,还要修改一部分BIOS的中断向量。有一部分中断向量是系统为用户保留的,如60H到67H号中断,用户可以将自己的中断服务程序写入这些中断向量中。不仅如此,用户还可以自己更改和完善系统已有的中断向量。
在C语言中,提供了一种新的函数类型interrupt,专门用来定义中断服务程序,比如我们可以写如下的中断服务程序:
/*例1:中断服务程序*/
void interrupt int60()
{
puts("This is an example");
}
该中断的功能就是显示一个字符串,为什么不用printf ( )函数呢?这就牵涉到DOS的重入问题,后面将作一些介绍。
一个简单的中断服务程序写好了,如何把它的函数入口地址填写到中断向量表中,以便在产生中断的时候能转入中断服务程序去执行呢?这里要用到setvect ( )和getvect ( )函数。setvect ( )有两个参数:中断号和函数的入口地址,其功能是将指定的函数安装到指定的中断向量中,getvect ( )函数有一个参数:中断号,返回值是该中断的入口地址。在安装中断以前,最好用disable ( )函数关闭中断,以防止在安装过程中又产生新的中断而导致程序运行混乱,待安装完成后,再用enable ( )函数开放中断,使程序正常运行。现在我们可以把上面的例子再丰富一下:
/*例2:中断服务程序的编写、安装和使用*/
#include
#include
#ifdef __cplusplus
#define __ARGU ...
#else
#define __ARGU
#endif
void interrupt int60 (__ARGU) /*中断服务函数*/
{
puts("This is an example");
}
void install (void interrupt (*fadd)(__ARGU),int num) /*安装中断*/
{
disable(); /*关闭中断*/
setvect(num, fadd); /*设置中断*/
enable(); /*开放中断*/
}
void main()
{
install (int60,0x60);/*将int60函数安装到0x60中断*/
geninterrupt (0x60); /*人为产生0x60号中断*/
}
有一定经验的读者很容易得到该程序的执行结果:在屏幕上显示“This is an example!”。
编写、安装中断服务程序的方法就介绍这些。下面再浅谈一下内存驻留程序(TSR)的编写和使用。在C语言中,可以用keep ( )函数将程序驻留内存。这个函数有两个参数:status和size。size为驻留内存长度,可以用size=_SS+_SP/16-_psp得到,当然这也是一种估算的方法,并不是精确值。函数执行完以后,出口状态信息保存在status中。比如,对于上面的例子,将“geninterrupt (0x60);”改写成“keep(0,_SS+_SP/16-_psp);”后再执行程序,这一段程序就被驻留,此后在其它的任何软件或程序设计中,只要用到了60H号中断,就会在屏幕上显示“This is an example!”的字样。要恢复系统对60H号中断的定义,只能重新启动计算机。
像上面的例子其实还很不完善,它没有考虑DOS系统环境的状态、没有考虑程序是否已经驻留内存、没有考虑退出内存驻留等问题。对于第二个问题还是很容易解决的:执行程序一开始就读取某一函数中断入口地址(如63H号中断)判断是否为空(NULL),如果为空就先将该地址置为非空再驻留内存,若为非空则表示已经驻留并退出程序。这一步判断非常重要,否则将会因为重复驻留占用过多内存空间而最后造成系统崩溃。至于其它两个问题,在此不多作说明,有兴趣的读者可以参考一些有关书籍。
不仅如此,我们还可以通过在DOS下使用热键(Hotkey)来调用内存驻留程序。比如将《希望汉字系统》自带的《希望词典》驻留内存后,在任意时刻按下Ctrl+F11键,就能激活程序,出现词典界面。微机的键盘中有一个微处理芯片,用来扫描和检测每个按键的按下和释放状态。大多数按键都有一个扫描码,告知CPU当前的状态,但一些特殊的键如PrintScreen、Ctrl+Break等不会产生扫描码,而直接产生中断。正因为如此,我们可以将Ctrl+Break产生的中断号指向我们自己写好的程序入口地址,那么当按下Ctrl+Break后,系统就会调用我们自己的程序去执行,这实际上也就是修改了Ctrl+Break的中断向量。至于其它按键激活程序则可以利用9H号键盘中断捕获的扫描码来实现,在此不多作说明。例如,执行下面的程序后,退回DOS系统,在任意的时候按下Ctrl+Break后,屏幕的底色就会变成红色。
/*例3:中断服务程序编写、安装和使用,内存驻留*/
#include
#include
#ifdef __cplusplus
#define __ARGU ...
#else
#define __ARGU
#endif
void interrupt newint(__ARGU); /*函数声明*/
void install (void interrupt (*fadd)(__ARGU), int num);
int main()
{
install (newint,0x1b); /*Ctrl+Break中断号:1BH*/
keep(0,_SS+(_SP/16)-_psp); /*驻留程序*/
return 0;
}
void interrupt newint(__ARGU)
{
textbackground(4); /*设置屏幕底色为红色*/
clrscr(); /*清除屏幕*/
}
void install (void interrupt (*fadd)(__ARGU), int num)
{
disable();
setvect(num,fadd); /*设置中断*/
enable();
}
由于13H号中断是BIOS提供的磁盘中断服务程序,对于DOS下的应用程序,它们的存盘、读盘功能都是通过调用这一中断来实现的。有许多DOS下的病毒就喜欢修改13H号中断来破坏系统,例如,修改13H号中断服务程序,将其改成:
/*例4:病毒体程序伪代码*/
void interrupt new13(__ARGU)
{
if (病毒发作条件成熟)
{ 修改入口参数指向病毒程序入口地址;
执行病毒代码;
}
调用原来的13H中断;
}
只要当任一软件(如EDIT.COM等)对磁盘有操作并且病毒发作条件成熟时,病毒就被激活。当然,这样做会导致可用内存空间减少,容易被用户发现。一些“聪明”的病毒又会去修改其它的中断向量,使得系统报告的内存大小和实际相符合。还有的病毒,当发现用户通过一些程序(如DEBUG.COM等)去跟踪它时,它会悄悄地溜掉,其基本原理仍然与修改中断有关。硬盘的0面0柱1扇区(Side 0 Cylinder 0 Sector 1)保存着重要的引导信息,一旦破坏,计算机将无法识别硬盘。我们可以写一个程序来防止任何软件(包括病毒)对这一扇区执行“写”操作,一定程度上实现了“写保护”的作用,它的基本原理就是修改13H号中断向量并常驻内存,监视着软件(包括病毒)对磁盘操作的每一个细节。读者请注意:本程序没有考虑内存驻留的退出,如果想恢复13H号中断,请重新启动计算机。
/*例5:主引导扇区保护,请用Turbo C 2.0编译,MBSP.C*/
#include
#include
#include
#define STSIZE 8192
#define PSP_ENV_PSP 0x2c
#define PARA(x) ((FP_OFF(x)+15)>>4)
typedef struct {
unsigned bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags;
} INTERRUPT_PARAMETER;
void install (void interrupt (*faddress)(), int num);
void interrupt new13(INTERRUPT_PARAMETER p);
int main()
{
union REGS regs;
struct SREGS sregs;
unsigned mem;
unsigned far *pointer;
char far *stack;
printf("\n<> version 1.0\n\n");
if ((stack=malloc(STSIZE))==NULL)
{
printf ("Not enough Memory!\n");
exit(1);
}
if (getvect(0x62)!=NULL)
{
printf("Already Installed!\n");
exit(1);
}
install(getvect(0x13),0x62);
install (new13,0x13);
pointer=MK_FP(_psp,PSP_ENV_PSP);
freemem(*pointer);
segread(&sregs);
mem=sregs.ds+PARA(stack)-_psp;
setblock(_psp,mem);
keep (0,mem);
return 0;
}
void install (void interrupt (*faddress)(), int num)
{
disable();
setvect(num,faddress);
enable();
}
void interrupt new13(INTERRUPT_PARAMETER p)
{
p.ax=_AX;
p.cx=_CX;
p.dx=_DX;
if(_AH==0x03&&_CH==0&&_CL==0x01&&_DH==0&&_DL==0x80) return;
enable();
geninterrupt (0x62);
disable();
_AX=p.ax;
_CX=p.cx;
_DX=p.dx;
return;
}
说明:在使用本程序以前,请:①用杀毒软件对计算机引导扇区、内存和所有文件进行一次全面的扫描,确信计算机中没有任何病毒;②有计算机汇编语言基础的读者可以自己写一个新的引导程序,先将本程序驻留内存,再调用原来的引导程序,以便在病毒还没有取得系统控制权以前开启防护功能。
最后简要说明一下DOS系统重入问题。DOS是单用户单任务操作系统。如果程序在执行的过程中被打断,就有可能因为破坏了原来的程序运行环境而造成运行不正常,这是灾难性的。当中断产生后,CPU立即中止当前的程序去执行中断服务程序,如果在中断服务程序中又有对DOS中断的调用(如DOS的21H号中断)时,这样必定会重写环境全局变量(例如PSP程序段前缀就会被改成正在执行的中断程序的PSP),这样原来的环境被破坏,原来的程序也就无法正确执行。当中断调用完成并返回后,用户得到的结果是出乎意料的。所以在编写中断服务程序时应该避免DOS系统功能调用,在C语言的中断服务程序中不应该出现malloc ( )、printf ( )、sprintf ( )等函数。
[url]
http://blog.sina.com.cn/s/blog_4a92ce12010006e3.html
[/url]
分享到:
相关推荐
"《计算机操作系统》进程的软中断通信" 计算机操作系统中,进程之间的通信是非常重要的,软中断信号是一种常用的通信机制。在本实验中,我们将学习如何使用软中断信号来实现进程之间的通信。 一、软中断信号的概念...
进程的软中断通信 2[实验目的] (1)理解掌握软中断的概念和技术; (2)掌握进程之间基于软中断的通信技术。 3[实验内容] 编写一段程序,父进程创建一个子进程p1;并使子进程利用系统调用kill()向...
这个"软中断开发实例6-13"很可能是一个深入探讨软中断使用的教程或代码示例,对于理解和实践软中断编程有着极大的价值。 软中断,不同于硬件中断,是由软件触发的中断事件。在Linux系统中,它们通常用于异步事件的...
进程的软中断通信和管道通信 在操作系统中,进程通信是指多个进程之间的信息交换和协作。进程通信的实现方法有很多,包括软中断通信和管道通信。本文将详细介绍这两种通信方法。 一、软中断通信 软中断通信是指...
软中断,又称软件中断,是处理器的一种机制,用于实现底层驱动和操作系统内核之间的快速交互。在本源代码示例中,"进程的软中断通讯"将这两者结合,提供了一种在用户空间进程与内核之间高效通信的方式。 首先,我们...
在嵌入式系统开发中,"ARM裸机软中断"是指在没有操作系统支持的情况下,通过软件方式触发中断处理机制。这种技术通常用于低级编程,例如设备驱动或实时系统的实现,因为它提供了对硬件中断的精细控制。下面我们将...
"将网卡软中断绑定指定CPU" 本文将讲解如何将网卡软中断绑定到指定的CPU上,以提高系统的性能和稳定性。 什么是软中断? 软中断(Softirq)是一种特殊的中断机制,它允许操作系统将中断处理程序绑定到特定的CPU上...
### 软中断实验知识点详解 #### 一、软中断概念及应用背景 软中断(Software Interrupt)是一种中断处理机制,通常用于操作系统或其他程序中,以便执行特定功能或调用某些服务例程。在微机原理与单片机技术中,软...
本文将详细探讨两种特定的IPC方式:软中断通信和管道通信。 首先,我们来看“进程间软中断通信”。在计算机系统中,中断是一种硬件机制,用于通知CPU某些事件已经发生。软中断,也称为软件中断,是由软件生成的一种...
这款处理器支持多种操作系统,包括Linux,其核心特性之一就是具备处理软中断(Software Interrupt,SWI)的能力。软中断是一种软件触发的中断机制,用于在用户模式和系统模式之间切换,执行一些特权级的操作或服务。...
### Linux实现软中断通信和管道通信相关知识点 #### 软中断通信 **软中断通信**是一种进程间的通信方式,它允许一个进程通过发送特定的信号来与其他进程进行交互。在本实验中,通过一系列系统调用来实现这一功能。...
在本课题“基于软中断的进程间通信的设计”中,我们将探讨如何利用软中断机制实现高效的进程间通信。软中断是计算机系统中的一种中断处理方式,与硬件中断相对,它通常由软件触发,例如操作系统内部函数调用。 首先...
此外,对于软中断的优化,常见的策略包括减少不必要的软中断触发,合并相似的软中断处理,以及合理安排软中断的执行时机。 总之,Linux内核软中断是操作系统中的关键组成部分,它允许内核高效地处理大量的并发任务...
《优化Linux网络处理性能的软中断处理机制》 在Linux操作系统中,网络处理性能的优化是提高系统整体效率的关键之一。软中断作为处理网络数据包的主要机制,其性能直接影响到系统的响应速度和吞吐量。文章针对软中断...
### 进程通信——软中断 #### 背景与概念 在计算机科学领域,进程间的通信(IPC)是多进程或线程程序设计中的一个关键环节,它允许不同的进程间共享数据、同步操作以及相互协作。软中断作为一种特殊的进程间通信...
linux软中断,软中断是linux系统原“底半处理”的升级,在原有的基础上发展的新的处理方式,以适应多cpu 、多线程的软中断处理。
本实验主要探讨了两种通信方式:进程的软中断通信和管道通信,都是在Linux环境下进行的。 首先,我们来看进程的软中断通信。软中断是由软件触发的一种中断机制,通常用于进程间的同步和信号传递。在这个实验中,父...
标题提到的"swi.rar_libstubs.a_swi软中断_软中断"是针对S3C2410处理器的一种软中断实现,其中"swi.rar"可能是一个包含源代码或二进制文件的压缩包,"libstubs.a"则是一个静态链接库,用于提供软中断相关的函数接口...
本文以ARM7内核的LPC2458 MCU,采用软中断的方法实现片外FLASH在运行程序时,同时实现对此FLASH的写操作例程。详细描述了ARM7内核的MCU软中断程序的设计方法。希望能对使用ARM7内核、Cortex-M3/M4内核的MCU,实现软...
标题中的“使用内核软中断的zigbee转串口驱动设计”涉及到的是在Linux操作系统下,为Zigbee设备开发一个驱动程序,该驱动利用内核软中断技术将Zigbee无线通信的数据转换为通过串行接口(UART)传输的数据。...