556次
trap函数
莱昂的赏析对照明晰。在这里我只注明几个容易让人感到要挟的题目。
起首是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 number为index访问该数组即可找到该系统调用的处置步伐。
一个比照难解之处是对付system call处理的第2754行:
“2754: callp = &sysent[fuiword(pc-2)&077];”
还记得咱们曩昔对trap指令的注明吗——trap指令用于完成system call,厥后8个bit(unix用来6个bit)
是system entry number——但是,pc不是就在栈里(参数)里,直接拿来用不就患了,2754这个古怪
的哄骗在做甚么?只管不成,因为压栈的pc是upgraded 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的优先级——这增加了return回trap(汇编例程)后,发展process switch的机缘。
下一节我们持续讨论系统挪用。
【注】:我们的探求跳过了关于swap、signal的一小块。
下一篇: 没有了