(莱昂氏unix源代码分析导读-22) trap函数(2693)

本文详细解析了UNIX系统中trap函数的工作原理,包括参数列表的来源、进程状态检查、系统调用处理及参数传递。通过分析栈图,解释了如何获取和使用寄存器,并探讨了system entry call的实现,特别是system call处理程序的查找方式。此外,还提到了trap函数在退出时可能调用setpri()调整进程优先级的情况。
摘要由CSDN通过智能技术生成

莱昂的分析比较清晰。在这里我只说明几个容易让人感到迷惑的问题。

 

首先是trap函数的长长的参数列表,同clock函数一样,这些参数来自于入口处的设置,

回头看一下栈图,这些参数的容易理解了。

 

函数开头就检查进程的“前状态”——绝大多数情况下,应该是user态。核态的陷入在

大多数情况下都是一个错误,会引起panic的调用,导致系统down掉。

 

在“2701: u.u_ar0 = &r0;”中,r0是函数的参数,而非PDP11寄存器。设置之后,通过u_ar0数组

可以神奇的取用各个寄存器,各个寄存器的数组标号定义如下:

 

2605: #define R0 (0)

2606: #define R1 (-2)

2607: #define R2 (-9)

2608: #define R3 (-8)

2609: #define R4 (-7)

2610: #define R5 (-6)

2611: #define R6 (-3)

2612: #define R7 (1)

2613: #define RPS (2)

 

要想弄懂这个问题,还得靠我们的老朋友——栈图,如下图所示:

 

 

您需要结合这两幅栈图,可以很容易的理解上述问题。

 

Trap处理多种类型的陷入中,最重要的要数system entry call了。系统定义了

sysent数组用于配置各个systerm call的处理程序。

 

2667: struct sysent {

2668:       int count;       /* argument count */

2669:       int (*call)();     /* name of handler */

2670: } sysent[64];

 

强调一下:这里的参数个数,指的是紧跟在“trap指令”后面传进来的参数,呆会我们

会看到,trap(2693)函数会将存放在u.u_arg[ ]数组中。而system call还可以通过r0传入一个

参数,这个参数在sysent[ ]中是不计数的。

 

2910: int sysent[]

2911: {

2912:    0, &nullsys,    /* 0 = indir */

2913:    0, &rexit,      /* 1 = exit */

2914:    0, &fork,      /* 2 = fork */

……

2923:    2, &exec,      /* 11 = exec */

……

2946     0, &nice,      /* 34 = nice */

2947:    0, &sslep,      /* 35 = sleep *

…..

}

 

显然,以system entry numberindex访问该数组即可找到该系统调用的处理程序。

 

一个比较难懂的地方是关于system call处理的第2754行:

2754: callp = &sysent[fuiword(pc-2)&077];

 

还记得我们以前对trap指令的说明吗——trap指令用于实现system call,其后8bitunix用来6bit

system entry number——但是,pc不是就在栈里(参数)里,直接拿来用不就得了,2754这个古怪

的操作在干什么?当然不行,因为压栈的pcupgraded pc,正好在trap指令的后面一个word。而2754

正好能取到trap这条指令的code

 

对于大多数系统调用来说,参数就跟在trap指令的后面,“trap函数”会依次取得参数,放入

u_arg[]数组之中,如下所示:

 

2765: for(i=0; i<callp->count; i++) {

2766:    u.u_arg[i] = fuiword(pc);

2767:    pc =+ 2;

2768: }

 

而#0系统调用是“间接”系统调用,经其传送的参数是位于用户程序数据空间中一个系统

调用及其参数序列的起始地址。取得参数之后,会通过trap1函数调用真正的系统调用处理程序。

 

还有一点需要注意的是,多数情况下,trap()函数在退出时,会调用setpri()重新设置active

process的优先级——这增加了returntrap(汇编例程)后,进行process switch的机会。

 

下一节我们继续讨论系统调用。

【注】:我们的讨论跳过了关于swapsignal的部分。

 

 

博客地址:http://blog.csdn.net/cszhao1980

博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值