软中断

软中断一般是指由指令int引起的“伪”中断动作——给CPU制造一个中断的假象;而硬中断则是实实在在由8259的连线触发的中断。因此,严格的讲,int与IRQ毫无关系,但二者均与中断向量有关系。int引起的中断,CPU是从指令中取得中断向量号;而IRQ引起的中断,CPU必须从数据线上取回中断号(硬件引发中断首先加到8259的某个IRQ引脚上,8259根据定义好的规则换算出相应的中断向量号,将其放在数据线上,然后通知CPU中断到来)。接下来CPU的工作就一样了:保护现场、根据中断号得到中断处理程序地址、执行中断处理、恢复现场继续执行被中断的指令。Windows驱动程序一般不能直接接管中断,中断是由内核的VPICD接管,驱动程序只是向VPICD注册中断服务,中断服务将由VPICD调用。这样可以有效的实现虚拟设备:虚拟不存在的设备或者改变已存在的物理设备的行为。

 

 

 

Linux用int $80来实现系统调用异常 .这一指令使用中断/异常向量号128(即16进制的80)将控制权转移给内核。为达到在使用系统调用时不必用机器指令编程,在标准的C语言库中为每一系统调用提供了一段短的子程序,完成机器代码的编程工作。事实上,机器代码段非常简短。它所要做的工作只是将送给系统调用的参数加载到CPU寄存器中,接着执行int $0x80指令。然后运行系统调用,系统调用的返回值将送入CPU的一个寄存器中,标准的库子程序取得这一返回值,并将它送回用户程序.
一般现在的核心有190个左右的系统调用
,可以看/usr/src/linux/代码目录下的
5.init/main.c
6.arch/i386/kernel/traps.c
7.arch/i386/kernel/entry.S
8.arch/i386/kernel/irq.h
9.include/asm-386/unistd.h
几个文件

希望与你共进步

 

1、内中断(软中断)  
  指CPU执行某些特殊操作或由INT指令引起的中断  
  ①   被零除操作或OF=1时执行INTO指令引起  
  ②   使用DEBUG中的单步或断点设置操作引起  
  ③   执行INT   n   指令引起  
   
   
  指外部芯片通过  
  CPU的INTR引脚或NMI引脚  
  发出中断申请引起的中断。  
   
  当INTR上有高电平信号  
  当NMI上有上升沿信号  
   
    可屏蔽中断  
      由INTR引脚引起的中断,称可屏蔽中断。  
    CPU是否响应INTR引脚上的中断请求取决于IF标志:  
      IF=1,CPU响应INTR引脚上的中断请求  
      IF=0,CPU不响应INTR引脚上的中断请求  
            即当IF=0时,将INTR引脚上的中断申请屏蔽。    

 

 

 

"软中断"对应的英文单词是"software   interrupt"  
  "硬中断"对应的英文单词是"hardware   interrupt"  
          有三种类型的中断:  
  (1)traps(可翻译为"自陷",同时在一些地方称做"software   interrupt(可翻译为软中断)";  
  (2)exceptions(可翻译为“异常”)  
  (3)interrupts(也可称为“hardware   interrupts")  
  interrupts   是有外部设备引起的中端。  
  traps   是使用int   n这样的指令引起的中断  
  exceptions   类似于traps。但有所不同。traps   是无条件的。当执行int   n时,系统就去调用n所对应的中断服务程序。  
  而except是某些程序执行中,出现了一些异常情况时(比如说,出现除领的情况),系统就会调用异常服务程序。这是有条件的。  

 


在软中断和硬中断之间的区别是什么?
①硬中断是由外部事件引起的因此具有随机性和突发性;软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的。
②硬中断的中断响应周期,CPU需要发中断回合信号(NMI不需要),软中断的中断响应周期,CPU不需发中断回合信号。
③硬中断的中断号是由中断控制器提供的(NMI硬中断中断号系统指定为02H);软中断的中断号由指令直接给出,无需使用中断控制器。
④硬中断是可屏蔽的(NMI硬中断不可屏蔽),软中断不可屏蔽。 

 

 
 
 
编制一段程序,使其实现进程的软中断通信。
要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断
信号;当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后
分别输出下列信息后终止:
Child  Process11 is  Killed  by  Parent!
Child  Process12 is  Killed  by  Parent!
父进程等待两个子进程终止后,输出如下的信息后终止:
Parent  Process  is  Killed!
 
#include
#include
#include
int wf; /*定义等待标记,当其为1时,表示需要等待*/
void waiting()

while(wf!=0);
}
void stop()
{ wf=0;
}
main()
{  
int p1,p2; /*定义两个进程号变量*/
while((p1=fork())==-1); /*循环创建进程至成功为止*/
   if(p1==0)
   {
   wf=1; /*将等待标记置1直到中断信号刺激stop*/
   signal(16,stop); /*接收到软中断信号16,转stop*/
   waiting();/*在wf置0前,不可往下执行*/
   lockf(1,1,0);
   printf("Child process 11 is killed by parent!/n");/*接收到父进程发送信号后,父进程杀死子进程11*/
   lockf(1,0,0); /*解锁*/
   exit(0);/*子进程11退出*/
   }
   else/*第二个子进程在判断为父进程后再创建.这样可以避免了在第一进程中再次创建下一级的一个子进程*/
  {
         while((p2=fork())==-1);
   if(p2==0)
    {
       wf=1; /*将等待标记置1直到中断信号刺激stop*/
   signal(17,stop); /*接收到软中断信号17,转stop*/
   waiting();/*在wf置0前,不可往下执行*/
   lockf(1,1,0); /*加锁*/
   printf("Child process 12 is killed by parent!/n");
   lockf(1,0,0);
   exit(0); /*子进程12退出*/
    }
    else
  {
   wf=1; /*将等待标记置1直到中断信号刺激stop*/
  signal(SIGINT,stop); /*若捕捉到键盘上来的中断信号转stop*/
  waiting();
  kill(p1,16); /*向子进程p1发软中断信号16*/
  kill(p2,17);
  wait(0); /*等待子进程死信号*/
  wait(0);
  printf("Parent process is killed!/n");/*接收到子进程死信号后,杀死父进程*/
  exit(0); /*父进程退出*/
  }
     }  
}
实验三 软中断通信
实验目的
1、了解什么是信号
2、熟悉LINUX系统中进程之间软中断通信的基本原理
实验内容
1、编写程序:用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按^c键);捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:
Child process1 is killed by parent!
Child process2 is killed by parent!
父进程等待两个子进程终止后,输出如下的信息后终止:
Parent process is killed!
2、分析利用软中断通信实现进程同步的机理
实验指导
一、信号
1、信号的基本概念
每个信号都对应一个正整数常量(称为signal  number,即信号编号。定义在系统头文件中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程发生了某异常事件。每个进程在运行时,都要通过信号机制来检查是否有信号到达。若有,便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;处理结束后再返回到原来的断点继续执行。实质上,信号机制是对中断机制的一种模拟,故在早期的UNIX版本中又把它称为软中断。
信号与中断的相似点:
(1)采用了相同的异步通信方式;
(2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;
(3)都在处理完毕后返回到原来的断点;
(4)对信号或中断都可进行屏蔽。
信号与中断的区别:
(1)中断有优先级,而信号没有优先级,所有的信号都是平等的;
(2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;
(3)中断响应是及时的,而信号响应通常都有较大的时间延迟。
信号机制具有以下三方面的功能:
(1)发送信号。发送信号的程序用系统调用kill( )实现;
(2)预置对信号的处理方式。接收信号的程序用signal( )来实现对处理方式的预置;
(3)收受信号的进程按事先的规定完成对相应事件的处理。
2、信号的发送
信号的发送,是指由发送进程把信号送到指定进程的信号域的某一位上。如果目标进程正在一个可被中断的优先级上睡眠,核心便将它唤醒,发送进程就此结束。一个进程可能在其信号域中有多个位被置位,代表有多种类型的信号到达,但对于一类信号,进程却只能记住其中的某一个。
进程用kill( )向一个进程或一组进程发送一个信号。
3、对信号的处理
当一个进程要进入或退出一个低优先级睡眠状态时,或一个进程即将从核心态返回用户态时,核心都要检查该进程是否已收到软中断。当进程处于核心态时,即使收到软中断也不予理睬;只有当它返回到用户态后,才处理软中断信号。对软中断信号的处理分三种情况进行:
(1)如果进程收到的软中断是一个已决定要忽略的信号(function=1),进程不做任何处理便立即返回;
(2)进程收到软中断后便退出(function=0);
(3)执行用户设置的软中断处理程序。
二、所涉及的中断调用
1、kill( )
系统调用格式
int  kill(pid,sig)
参数定义
int  pid,sig;
其中,pid是一个或一组进程的标识符,参数sig是要发送的软中断信号。
(1)pid>0时,核心将信号发送给进程pid。
(2)pid=0时,核心将信号发送给与发送进程同组的所有进程。
(3)pid=-1时,核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。
2、signal( )
预置对信号的处理方式,允许调用进程控制软中断信号。
系统调用格式
signal(sig,function)
头文件为
                   #include
参数定义
signal(sig,function)
int  sig;
void (*func) ( )
其中sig用于指定信号的类型,sig为0则表示没有收到任何信号,余者如下表:
值 名  字 说          明
01 SIGHUP 挂起(hangup)
02 SIGINT 中断,当用户从键盘按^c键或^break键时
03 SIGQUIT 退出,当用户从键盘按quit键时
04 SIGILL 非法指令
05 SIGTRAP 跟踪陷阱(trace trap),启动进程,跟踪代码的执行
06 SIGIOT IOT指令
07 SIGEMT EMT指令
08 SIGFPE 浮点运算溢出
09 SIGKILL 杀死、终止进程
10 SIGBUS 总线错误
11 SIGSEGV 段违例(segmentation  violation),进程试图去访问其虚地址空间以外的位置
12 SIGSYS 系统调用中参数错,如系统调用号非法
13 SIGPIPE 向某个非读管道中写入数据
14 SIGALRM 闹钟。当某进程希望在某时间后接收信号时发此信号
15 SIGTERM 软件终止(software  termination)
16 SIGUSR1 用户自定义信号1
17 SIGUSR2 用户自定义信号2
18 SIGCLD 某个子进程死
19 SIGPWR 电源故障
   
function:在该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用该函数,对除了信号SIGKILL,SIGTRAP和SIGPWR以外的信号,核心自动地重新设置软中断信号处理程序的值为SIG_DFL,一个进程不能捕获SIGKILL信号。
function 的解释如下:
(1)function=1时,进程对sig类信号不予理睬,亦即屏蔽了该类信号;
(2)function=0时,缺省值,进程在收到sig信号后应终止自己;
(3)function为非0,非1类整数时,function的值即作为信号处理程序的指针。
三、参考程序
#include
#include
#include
void waiting( ),stop( );
int wait_mark;
main( )
{
int p1,p2,stdout;
while((p1=fork( ))= =-1);       /*创建子进程p1*/
if (p1>0)
            {
while((p2=fork( ))= =-1);     /*创建子进程p2*/
if(p2>0)
{
                    wait_mark=1;
signal(SIGINT,stop);   /*接收到^c信号,转stop*/
waiting( );
kill(p1,16);        /*向p1发软中断信号16*/
kill(p2,17);        /*向p2发软中断信号17*/
wait(0);           /*同步*/
wait(0);
printf("Parent process is killed!/n");
exit(0);
}
           else
             {
                    wait_mark=1;
signal(17,stop);   /*接收到软中断信号17,转stop*/
waiting( );
lockf(stdout,1,0);
printf("Child process 2 is killed by parent!/n");
lockf(stdout,0,0);
exit(0);
}
}
else
{
wait_mark=1;
signal(16,stop);        /*接收到软中断信号16,转stop*/
waiting( );
lockf(stdout,1,0);
printf("Child process 1 is killed by parent!/n");
lockf(stdout,0,0);
exit(0);
}
   }
void waiting( )
{
 while(wait_mark!=0);
}
void stop( )
{
wait_mark=0;
}
四、运行结果
屏幕上无反应,按下^C后,显示  Parent  process  is  killed!
五、分析原因
上述程序中,signal( )都放在一段程序的前面部位,而不是在其他接收信号处。这是因为signal( )的执行只是为进程指定信号值16或17的作用,以及分配相应的与stop( )过程链接的指针。因而,signal( )函数必须在程序前面部分执行。
本方法通信效率低,当通信数据量较大时一般不用此法。
六、思考
1、该程序段前面部分用了两个wait(0),它们起什么作用?
2、该程序段中每个进程退出时都用了语句exit(0),为什么?
3、为何预期的结果并未显示出?
4、程序该如何修改才能得到正确结果?
5、不修改程序如何得到期望的输出?

本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/Non_Recursive/archive/2009/04/11/4065440.aspx

你可能感兴趣的:(kernel)