《返璞归真--UNIX技术内幕》--第6章 中断处理过程

简介: 6.4  PDP 11/40的中断类型 系统中的中断主要有下面几种。 6.4.1  电传终端接口输入中断 电传终端接口用于链接PDP 11/40的总线和主要的输入、输出终端,当时该终端是电传打字机,这也是UNIX中用tty(teletypewriter)表示进程所使用的终端类型的原因,事实上电传接口还可以连接彩色显示器(CRT)等。

6.4  PDP 11/40的中断类

系统中的中断主要有下面几种。

6.4.1  电传终端接口输入中断

电传终端接口用于链接PDP 11/40的总线和主要的输入、输出终端,当时该终端是电传打字机,这也是UNIX中用ttyteletypewriter)表示进程所使用的终端类型的原因,事实上电传接口还可以连接彩色显示器(CRT)等。输入中断是用户在终端输入字符时所触发的中断,它的优先级为4级。在中断中这是最低优先级,它的入口函数是klin,其服务函数的C语言部分是klrint函数。

6.4.2  电传终端接口输出中断

该中断在字符显示在电传接口所连接的终端时产生,它的优先级也是4级。它的入口函数是klou,其服务函数的C语言部分是klxint函数。

6.4.3  纸带打孔机输入中断

纸带打孔机是老式计算机经常使用的一种输入输出设备。纸带上有没有小孔代笔二进制数字10。这样,打上一系列小孔的纸带就代表了一连串的二进制数。打孔机在读取纸带时,以固定的速率、每隔固定的长度读取二进制数,如果该位置被打上小孔,则认为该值是1(或0,视设计而定),否则认为是相反的数字值。纸带输入中断的优先级是4级,入口函数是pcin,其服务函数的C语言部分是pcrint

6.4.4  纸带打孔机输出中断

和输入相反,输出操作在光滑的纸带上按照需要输出的数据在特定的位置打上小孔。输出中断的优先级也是4级,入口函数是pcou,其服务函数的C语言部分是pcpint

6.4.5  时钟中断

它是系统中优先级最高的中断,它的优先级为6。它又可分为两种:线频时钟中断(Line Clock)和可编程时钟中断(RTC—Real Time Clock)。就功能上而言,它们并无大的不同,所以具有相同的中断入口函数kwlp,中断服务函数的C语言部分是clock

6.4.6  行打印机中断

它只有一个(输出)中断入口:lpou。它的优先级是4,中断服务函数的C语言部分是lpint

6.4.7  磁盘读写中断

每一次磁盘读写操作完成后,都会产生磁盘读写中断。它的入口函数是rkio,其优先级为5,中断服务函数的C语言部分是rkintr


 

6.5  一些常用函

这里介绍一下m40.s中定义的一些常用函数。

6.5.1  特殊指令

mfpi, mtpi指令主要用于当前模式和之前模式之间的数据传输。mfpi从之前模式的指定地址处读取一个字存放到当前模式下的栈上;mtpi则相反,读取当前模式栈顶的字,写入到之前模式下的指定地址处。

6.5.2  fubyte(fuibyte)

函数原型:char fubyte(int addr);

功能描述:从之前模式下addr地址空间处读取1个字节,并返回其值。如果读取过程出错,函数返回-1

参数说明:addr是所要读取的数据所在地址值。

-----------------------选自光盘文件/usr/sys/conf/m40.s-----------------------
1. .globl _fubyte, _subyte
      /* -------------------------
2. .globl _fuibyte, _suibyte
      /* -------------------------
3. .globl _fuword, _suword
      /* -------------------------*/
4. .globl _fuiword, _suiword    
5. _fuibyte:            
6. _fubyte:
7.     mov 2(sp),r1    
8.     bic $1,r1    
9.     jsr pc,gword    
10.     cmp r1,2(sp)
11.     beq 1f
12.     swab r0        
14. 1:
15.     bic $!377,r0    
16.      rts pc


6-7  程序进入fubyte后的栈分布

 

1 4 行声明函数为全局,从而使C 语言代码可以调用它们。

在进入fubyte时,栈空间分布如图6-7所示。

100702214500.jpg

6-7  程序进入fubyte后的栈分布


7行就是取出参数addr值给r1

由于读字节时的地址addr可能是奇地址,所以第8行清除最低位(位0)取addr所属的偶地址,如果addr是奇地址的话。比如,地址1属于地址0所在的字,地址3属于地址2所在的字,一般地,有地址2n+1属于地址2n所在的字(n>=0)。当然如果addr本身就是偶地址,那么该操作不会对addr值有影响。

9行跳转到gword中运行,gword和其他一些函数定义如下。


1.    gword:                        //get word,从之前模式的地址r1处读取一个字
2.        mov PS,-(sp)
3.        bis $340,PS         //屏蔽所有中断
4.        mov nofault,-(sp)
5.        mov $err,nofault     //设置出错处理函数为err
6.        mfpi (r1)                //从之前模式的地址r1处读取一个字到当前栈顶
7.        mov (sp)+,r0            //把读取的字赋给r0
8.        br 1f            

9.    pword:                        //put word,向之前模式的地址r1处写入一个字
10.        mov PS,-(sp)
11.        bis $340,PS            
12.        mov nofault,-(sp)
13.        mov $err,nofault
14.        mov r0,-(sp)
15.        mtpi (r1)                //把当前栈顶字写到之前模式的地址r1处
16.    1:
17.        mov (sp)+,nofault
18.        mov (sp)+,PS
19.        rts pc

20.    err:
21.        mov (sp)+,nofault    //恢复全局变量nofault的值
22.        mov (sp)+,PS            //恢复PSW的值
23.        tst (sp)+            
24.        mov $-1,r0            //设置返回值为-1
25.        rts pc        


2行保存PS,为下一行关中断做准备。第3行关闭7级中断,事实上目前系统中优先级最高的中断是6级,这样做为安全起见,而且为将来系统的变化而提供扩展性。

4行保存nofault值到栈。

5行赋nofault值为错误处理函数err的地址。

6行从r1指向的之前模式下的地址空间读取一个字,并存放到当前栈上。这个读取过程有可能成功,也有可能会失败。

—     如果读取成功,那么第7行把读出的字节值存到寄存器r0中,跳转到第23行。第24行恢复nofault的值,第25行恢复PS值为调用gword之前的值,第26行返回到调用者,这里是fubyte,则继续fubyte中第10行执行。第10行比较r1和实际参数addr,这是因为r1addr所属字的偶地址,如果addr是偶地址,那么r1=addr,否则r1addrr0是从地址r1处读出的一个字的值,所以如果r1=addr,那么所需要读取的字节值就是r0的低字节,因此直接跳转到第14行清除r0的高字节;如果r1addr,那么所需要读取的字节值就是r0的高字节,因此第12行交换r0的高低字节。最后在第15行返回到调用者,返回值是r0

—     如果读取失败,那么大多数情况是由于r1指向的地址不存在而产生总线超时自陷,或者由于该地址不在当前页内而产生内存管理违例自陷,不管产生何种自陷,程序都将被打断而跳转到trap函数中运行。根据第7章的讲述,我们知道trap函数将返回到nofault中保存的错误处理函数在这里也就是在err函数中运行。这时栈分布如图6-8所示:

100702214730.jpg
6-8  mfpi 执行出错后的栈分布


再来看看err函数。

2122行恢复nofaultPS的值,第23行增加栈指针,使其指向“返回到fubyte的调用者PC”。第24行设置r0(返回值)为-1,最后在第25行直接返回到fubyte的调用者。这一段处理过程有些复杂,其流程图如图6-9所示:

100702214741.jpg


6-9  fubyte 调用出错的指令执行流程

至此我们可以明白在main函数中,为何当fuibyte()返回-1时,表示该地址不存在。

6.5.3  fuword(fuiword)

函数原型:int fuword(int addr);

功能描述:从之前模式下addr地址处读取1个字,并返回其值。如果读取出错,则返回-1

参数说明:addr是所要读取的数据所在地址值。


-----------------------选自光盘文件/usr/sys/conf/m40.s-----------------------
1. _fuiword:
2. _fuword:
3.     mov 2(sp),r1
4. fuword:            
5.      jsr pc,gword
6.      rts pc

该函数的实现过程和fubyte基本一致,但由于是读取整个字的值,因此流程更简单。这里有点疑惑的地方是第4行的声明,似乎没有什么意义。

6.5.4  subyte(suibyte)

函数原型:int subyte(int addr,  char ch);

功能描述:向之前模式下addr地址处写入一个字节的值ch。函数返回0表示写入成功,-1表示写入失败。

参数说明:addr是所要写入的地址值。

ch是所要写入的值。

------------------------选自光盘文件/usr/sys/conf/m40.s----------------------
1.    _suibyte:
2.    _subyte:
3.        mov 2(sp),r1
4.        bic $1,r1
5.        jsr pc,gword
6.        mov r0,-(sp)
7.        cmp r1,4(sp)
8.        beq 1f
9.        movb 6(sp),1(sp)
10.        br 2f
11.    1:
12.        movb 6(sp),(sp)
13.    2:
14.        mov (sp)+,r0
15.        jsr pc,pword
16.        clr r0
17.        rts pc

进入subyte后的栈分布如图6-10所示:

3行赋addrr1。第4行同样清除r1最低位,使其等于addr所属字的偶地址,然后调用gword读出该地址处的字值。之所以这样做,是因为用mtpi指令向之前模式的地址空间写入数据时,只能单个字的写入,所以需要先读出整个字的值,再把需要写入的字节部分改成ch,然后再写入修改后的字。

100702214939.jpg

6-10  进入subyte后的栈分布图

上一章   进程管理和调度                                      目录                                   下一章   自陷

本书在全国各大书店均有销售!


目录
相关文章
|
Unix
和Steve之间的通信--RE: 关于《UNIX技术内幕》的勘误及遇到的问题_12
Steve,答复如下。From: quntmec@hotmail.comTo: qf.hao@hotmail.comSubject: 关于《UNIX技术内幕》的勘误及遇到的问题_12Date: Fri, 28 Oct 2011 21:46:12 +0800 郝先生,1、第158页,第2段第3、4行里提到的wakeup(&runin)可以改为 setrun(&proc[0]),我觉得直接替换不可以吧?如果真要替换,那也只能是设置一个循环遍历所有进程,符合唤醒条件的才 setrun(&proc[0])。
799 0
|
Unix
和Steve之间的通信--RE: 关于《UNIX技术内幕》的勘误及遇到的问题_10
Steve,mtpi是一个汇编指令,用于在内核模式和用户模式之间传递数据。在第18页有描述From: quntmec@hotmail.comTo: qf.hao@hotmail.comSubject: RE: 关于《UNIX技术内幕》的勘误及遇到的问题_10Date: Sun, 20 Nov 2011 17:01:08 +0800 郝先生,mtpi函数的代码在哪一页?我重新翻阅了一下,除了在第140页处(最后一段)可以找到一点有关mtpi的说明外,我没有发现书里有mtpi的代码。
866 0
|
Unix
和Steve之间的通信--关于《UNIX技术内幕》的勘误及遇到的问题_3
From: quntmec@hotmail.comTo: qf.hao@hotmail.comSubject: 关于《UNIX技术内幕》的勘误及遇到的问题_3Date: Thu, 6 Oct 2011 19:24:10 +0800 郝先生,对于启动模块这一章...
750 0
|
Unix
和Steve之间的通信--RE: 关于《UNIX技术内幕》的勘误及遇到的问题_4
Steve,应该是第2中情况,u变量就是一个user结构体,并且该变量地址固定在0o140000处,其所占空间长度就是结构体的长度。至于为什么要固定地址是0o140000,因为它是第6号虚拟寄存器映射的。
753 0
|
Unix
《返璞归真--UNIX技术内幕》--第14章 多线程的实现
14.1  概述 现代操作系统引入了线程的概念。线程是CPU执行的最小单元,相对于进程而言,它具有轻捷、高效、开销小等优点。 14.2  线程和经典进程的比较 线程和经典进程的主要区别如下。
848 0
|
Unix
《返璞归真--UNIX技术内幕》-- 第11章 UNIX可执行文件
11.1  .out文件 本版UNIX的可执行文件是.out格式,如果你在UNIX下用gcc编译程序,它默认会生成一个名为“a.out”的可执行文件。
841 0
|
存储 缓存 Unix
《返璞归真--UNIX技术内幕》--第9章 字符设备驱动
本系统中的输入输出设备都是字符设备,它们包括:KL-11/DL-11A——电传串行接口、PC-11——纸带打孔机和LP-11——行打印机。其中KL-11用于连接终端(terminal),作为用户键盘输入和显示输出的交互接口。
918 0
|
Unix
《返璞归真--UNIX技术内幕》--源代码
本源代码经宁希波帮助整理,去除了''和'&'符号,在此表示诚挚的谢意!源码中除/usr/personal目录外,均由Bell Labs(贝尔实验室)开发。
660 0
|
Unix
《UNIX技术内幕》--第3章 虚拟内存
Normal 0 false false false MicrosoftInternetExplorer4 /* Style Definitions */ table.
596 0
|
Unix Linux 调度
《UNIX技术内幕》勘误及问题解答_26
From: quntmec@hotmail.com To: qf.hao@hotmail.com Subject: 关于《UNIX技术内幕》的勘误及遇到的问题_26 Date: Sun, 26 Feb 2012 16:34:18 +0800 郝先生, 线程方面碰到的问题如下: 1、689页,倒数第2、3行,里面提到第14章所实现的线程在退出时只会将线程栈释放、而不会释放该线程所分配的堆空间,这是否会造成内存泄漏?[郝]:如果用户线程在每次调用malloc后,都会调用free来释放它,那么就不会有内存泄漏。
919 0