code:trap - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki

Table of Contents

Source

2682

2683 /*

2684  * Called from l40.s or l45.s when a processor trap occurs.

2685  * The arguments are the words saved on the system stack

2686  * by the hardware and software during the trap processing.

2687  * Their order is dictated by the hardware and the details

2688  * of C’s calling sequence. They are peculiar in that

2689  * this call is not ’by value’ and changed user registers

2690  * get copied back on return.

2691  * dev is the kind of trap that occurred.

2692  */

2693 trap(dev, sp, r1, nps, r0, pc, ps)

2694 {

2695     register i, a;

2696     register struct sysent *callp;

2697

2698     savfp();

2699     if ((ps&UMODE) == UMODE)

2700          dev =| USER;

  • 若 陷入前为用户态,向dev追加USER标志
  • UMODE 定义在 trap.c
2701     u.u_ar0 = &r0;
2702     switch(dev) {

2703

2704     /*

2705      * Trap not expected.

2706      * Usually a kernel mode bus error.

2707      * The numbers printed are used to

2708      * find the hardware PS/PC as follows.

2709      * (all numbers in octal 18 bits)

2710      * address_of_saved_ps =

2711      * (ka6*0100) + aps - 0140000;

2712      * address_of_saved_pc =

2713      * address_of_saved_ps - 2;

2714      */

2715     default:

2716          printf("ka6 = %o \n", *ka6);

2717          printf("aps = %o \n", &ps);

2718          printf("trap type %o \n", dev);

2719          panic("trap");

2720

2721     case 0+USER: /* bus error */

2722          i = SIGBUS;

2723          break;

2724

2725     /*

2726      * If illegal instructions are not

2727      * being caught and the offending instruction

2728      * is a SETD, the trap is ignored.

2729      * This is because C produces a SETD at

2730      * the beginning of every program which

2731      * will trap on CPUs without 11/45 FPU.

2732      */

2733     case 1+USER: /* illegal instruction */

2734          if(fuiword(pc-2)==SETD && u.u_signal[SIGINS]==0)

2735           goto out;

  • 若 当前指令为 SETD,并且用户不捕捉SIGINS信号,则跳过陷入(原因:参看 2725 - 2732)
2736          i = SIGINS;

2737          break;

2738

2739     case 2+USER: /* bpt or trace */

2740          i = SIGTRC;

2741          break;

2742

2743     case 3+USER: /* iot */

2744          i = SIGIOT;

2745          break;

2746

2747     case 5+USER: /* emt */

2748          i = SIGEMT;

2749          break;

2750

2751     case 6+USER: /* sys call */

2752          u.u_error = 0;

2753          ps =& ~EBIT;

  • 清 错误状态/标志
2754          callp = &sysent[fuiword(pc-2)&077];
  • callp ← 对应的系统调用入口
2755          if (callp == sysent) { /* indirect */
  • 若 callp 为0#系统调用入口(间接系统调用) (sysent[0] == sysent),...
  • 参看 系统调用#直接/间接系统调用
  • 以下代码完成的工作
    • 读入 送给系统调用处理函数 的参数
  • 2759 - 2760 的说明
    • 约定 间接系统调用 的编码形式为 01044XX (SYS 定义在 trap.c
    • 若 违反约定,则将系统调用号 置为 63(实际该系统调用不存在),将会抛出错误
2756           a = fuiword(pc);

2757           pc =+ 2;

2758           i = fuword(a);

2759           if ((i & ~077) != SYS)

2760                i = 077; /* illegal */

2761           callp = &sysent[i&077];

2762           for(i=0; i<callp-></callp->count; i++)

2763                u.u_arg[i] = fuword(a =+ 2);

2764          } else {

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

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

2767                pc =+ 2;

2768           }

2769          }

2770          u.u_dirp = u.u_arg[0];

  • 此句意图很隐晦,需要联系具体系统调用进行解释
    • 在 使用系统调用 open时,第一个参数是文件路径
    • open 中 调用 namei 查找与路径对应的文件,其中namei 的第一个参数为 uchar
    • uchar是用来获取文件名的函数
    • uchar 中通过u.u_dirp来获取文件名
    • 所以此处要将u.u_dirp指向第一个参数
2771          trap1(callp->call);

2772          if(u.u_intflg)

2773           u.u_error = EINTR;

  • 此处构成 系统调用函数 的出错处理,详细参看trap1 2848 的说明
2774          if(u.u_error < 100) {

2775           if(u.u_error) {

2776                ps =| EBIT;

2777                r0 = u.u_error;

2778           }

2779           goto out;

2780          }

2774 - 2780
  • 处理错误
  • EBIT 定义在 trap.c,对应 PS 的 C 位
2781          i = SIGSYS;

2782          break;

2783

2784     /*

2785      * Since the floating exception is an

2786      * imprecise trap, a user generated

2787      * trap may actually come from kernel

2788      * mode. In this case, a signal is sent

2789      * to the current process to be picked

2790      * up later.

2791      */

2792     case 8: /* floating exception */

2793          psignal(u.u_procp, SIGFPT);

2794          return;

2795

2796     case 8+USER:

2797          i = SIGFPT;

2798          break;

2799

2800     /*

2801      * If the user SP is below the stack segment,

2802      * grow the stack automatically.

2803      * This relies on the ability of the hardware

2804      * to restart a half executed instruction.

2805      * On the 11/40 this is not the case and

2806      * the routine backup/l40.s may fail.

2807      * The classic example is on the instruction

2808      * cmp -(sp),-(sp)

2809      */

2810     case 9+USER: /* segmentation exception */

2811          a = sp;

2812          if(backup(u.u_ar0) == 0)

2813           if(grow(a))

2814                goto out;

2815          i = SIGSEG;

2816          break;

2817     }

2818     psignal(u.u_procp, i);

2819

2820 out:

2821     if(issig())

2822          psig();

2823     setpri(u.u_procp);

2824 }

2825 /* ------------------------- */

Extend

附图

Ref

Caller

⚠️ **GitHub.com Fallback** ⚠️