Chinaunix首页 | 论坛 | 博客
  • 博客访问: 66113
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2015-10-15 14:23
个人简介

-计算机-每天学习一点专业知识

文章分类

全部博文(21)

文章存档

2019年(1)

2018年(15)

2015年(5)

我的朋友

分类: 其他UNIX

2015-11-09 11:45:21

    下面举例说明系统调用的全过程(以fork为例):
  1.     当用户进程调用fork时,-》\lib\libc\syscall\fork.S中去执行,

    点击(此处)折叠或打开

    1. #include <machine/asm.h>

    2. IMPORT(_fork)
    3. ENTRY(fork)
    4.     jmp    _C_LABEL(_fork)
  2. -》\lib\libc\posix\_fork.c

    点击(此处)折叠或打开

    1. #include <lib.h>
    2. #define fork _fork
    3. #include <unistd.h>

    4. PUBLIC pid_t fork()
    5. {
    6.   message m;

    7.   return(_syscall(PM_PROC_NR, FORK, &m));
    8. }
  3. -》\lib\nbsd_libc\sys-minix\syscall.c

    点击(此处)折叠或打开

    1. #include <sys/cdefs.h>
    2. #include <lib.h>
    3. #include "namespace.h"

    4. #ifdef __weak_alias
    5. __weak_alias(syscall, _syscall)
    6. #endif

    7. int _syscall(endpoint_t who, int syscallnr, message *msgptr)
    8. {
    9.   int status;

    10.   msgptr->m_type = syscallnr;
    11.   status = _sendrec(who, msgptr);
    12.   if (status != 0) {
    13.     /* 'sendrec' itself failed. */
    14.     /* XXX - strerror doesn't know all the codes */
    15.     msgptr->m_type = status;
    16.   }
    17.   if (msgptr->m_type < 0) {
    18.     errno = -msgptr->m_type;
    19.     return(-1);
    20.   }
    21.   return(msgptr->m_type);
    22. }
  4. -》\lib\nbsd_libc\arch\i386\sys-minix\_ipc.S

    点击(此处)折叠或打开

    1. #include <minix/ipcconst.h>
    2. #include <machine/asm.h>

    3.     IPCVEC = 33    /* ipc trap to kernel */
    4.     KERVEC = 32    /* syscall trap to kernel */

    5.     SRC_DST = 8    /* source/ destination process */
    6.     MESSAGE = 12    /* message pointer */
    7.     STATUS = 16    /* status pointer */

    8. /**========================================================================* */
    9. /* IPC assembly routines             * */
    10. /**========================================================================* */
    11. /* all message passing routines save ebx, but destroy eax and ecx. */
    12. ENTRY(_send)
    13.     push    %ebp
    14.     movl    %esp, %ebp
    15.     push    %ebx
    16.     movl    SRC_DST(%ebp), %eax    /* eax = dest-src */
    17.     movl    MESSAGE(%ebp), %ebx    /* ebx = message pointer */
    18.     movl    $SEND, %ecx    /* _send(dest, ptr) */
    19.     int    $IPCVEC    /* trap to the kernel */
    20.     pop    %ebx
    21.     pop    %ebp
    22.     ret

    23. ENTRY(_receive)
    24.     push    %ebp
    25.     movl    %esp, %ebp
    26.     push    %ebx
    27.     movl    SRC_DST(%ebp), %eax    /* eax = dest-src */
    28.     movl    MESSAGE(%ebp), %ebx    /* ebx = message pointer */
    29.     movl    $RECEIVE, %ecx    /* _receive(src, ptr) */
    30.     int    $IPCVEC    /* trap to the kernel */
    31.     movl    STATUS(%ebp), %ecx    /* ecx = status pointer */
    32.     movl    %ebx, (%ecx)
    33.     pop    %ebx
    34.     pop    %ebp
    35.     ret

    36. ENTRY(_sendrec)
    37.     push    %ebp
    38.     movl    %esp, %ebp
    39.     push    %ebx
    40.     movl    SRC_DST(%ebp), %eax    /* eax = dest-src */
    41.     movl    MESSAGE(%ebp), %ebx    /* ebx = message pointer */
    42.     movl    $SENDREC, %ecx    /* _sendrec(srcdest, ptr) */
    43.     int    $IPCVEC    /* trap to the kernel */
    44.     pop    %ebx
    45.     pop    %ebp
    46.     ret

    47. ENTRY(_notify)
    48.     push    %ebp
    49.     movl    %esp, %ebp
    50.     push    %ebx
    51.     movl    SRC_DST(%ebp), %eax    /* eax = destination */
    52.     movl    $NOTIFY, %ecx    /* _notify(srcdst) */
    53.     int    $IPCVEC    /* trap to the kernel */
    54.     pop    %ebx
    55.     pop    %ebp
    56.     ret

    57. ENTRY(_sendnb)
    58.     push    %ebp
    59.     movl    %esp, %ebp
    60.     push    %ebx
    61.     movl    SRC_DST(%ebp), %eax    /* eax = dest-src */
    62.     movl    MESSAGE(%ebp), %ebx    /* ebx = message pointer */
    63.     movl    $SENDNB, %ecx    /* _sendnb(dest, ptr) */
    64.     int    $IPCVEC    /* trap to the kernel */
    65.     pop    %ebx
    66.     pop    %ebp
    67.     ret

    68. ENTRY(_do_kernel_call)
    69.     /* pass the message pointer to kernel in the %eax register */
    70.     movl    4(%esp), %eax
    71.     int    $KERVEC
    72.     ret
  5. 语句(int 33)触发33号软中断,\common\include\arch\i386\interrupt.h中定义宏IPC_VECTOR(#include IPC_VECTOR 33),中断向量表gate_table在\kernel\arch\i386\protect.c中进行初始化,中断33的中断处理程序为ipc_entry。

    点击(此处)折叠或打开

    1. /* Build descriptors for interrupt gates in IDT. */
    2. PUBLIC void idt_init(void)
    3. {
    4.     struct gate_table_s gate_table[] = {
    5.         { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE },
    6.         { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE },
    7.         { nmi, NMI_VECTOR, INTR_PRIVILEGE },
    8.         { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE },
    9.         { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE },
    10.         { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE },
    11.         { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE },
    12.         { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE },
    13.         { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE },
    14.         { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE },
    15.         { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE },
    16.         { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE },
    17.         { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE },
    18.         { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
    19.         { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
    20.         { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
    21.         { alignment_check, ALIGNMENT_CHECK_VECTOR, INTR_PRIVILEGE },
    22.         { machine_check, MACHINE_CHECK_VECTOR, INTR_PRIVILEGE },
    23.         { simd_exception, SIMD_EXCEPTION_VECTOR, INTR_PRIVILEGE },
    24.         { ipc_entry, IPC_VECTOR, USER_PRIVILEGE },
    25.         { kernel_call_entry, KERN_CALL_VECTOR, USER_PRIVILEGE },
    26.         { NULL, 0, 0}
    27.     };

    28.     idt_copy_vectors(gate_table);
    29.     idt_copy_vectors(gate_table_pic);
    30. }

  6. -》\kernel\arch\i386\mpx.S

    点击(此处)折叠或打开

    1. /*
    2.  * IPC is only from a process to kernel
    3.  */
    4. ENTRY(ipc_entry)

    5.     SAVE_PROCESS_CTX(0)

    6.     /* save the pointer to the current process */
    7.     push    %ebp

    8.     /*
    9.      * pass the syscall arguments from userspace to the handler.
    10.      * SAVE_PROCESS_CTX() does not clobber these registers, they are still
    11.      * set as the userspace have set them
    12.      */
    13.     push    %ebx
    14.     push    %eax
    15.     push    %ecx

    16.     /* stop user process cycles */
    17.     push    %ebp
    18.     /* for stack trace */
    19.     movl    $0, %ebp
    20.     call    _C_LABEL(context_stop)
    21.     add    $4, %esp

    22.     call    _C_LABEL(do_ipc)

    23.     /* restore the current process pointer and save the return value */
    24.     add    $3 * 4, %esp
    25.     pop    %esi
    26.     mov %eax, AXREG(%esi)

    27.     jmp    _C_LABEL(switch_to_user)
  7. -》\kernel\arch\i386\arch_clock.c

    点击(此处)折叠或打开

    1. PUBLIC void context_stop(struct proc * p)
    2. {
    3.     u64_t tsc, tsc_delta;
    4.     u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
    5. #ifdef CONFIG_SMP
    6.     unsigned cpu = cpuid;

    7.     /*
    8.      * This function is called only if we switch from kernel to user or idle
    9.      * or back. Therefore this is a perfect location to place the big kernel
    10.      * lock which will hopefully disappear soon.
    11.      *
    12.      * If we stop accounting for KERNEL we must unlock the BKL. If account
    13.      * for IDLE we must not hold the lock
    14.      */
    15.     if (p == proc_addr(KERNEL)) {
    16.         u64_t tmp;

    17.         read_tsc_64(&tsc);
    18.         tmp = sub64(tsc, *__tsc_ctr_switch);
    19.         kernel_ticks[cpu] = add64(kernel_ticks[cpu], tmp);
    20.         p->p_cycles = add64(p->p_cycles, tmp);
    21.         BKL_UNLOCK();
    22.     } else {
    23.         u64_t bkl_tsc;
    24.         atomic_t succ;
    25.         
    26.         read_tsc_64(&bkl_tsc);
    27.         /* this only gives a good estimate */
    28.         succ = big_kernel_lock.val;
    29.         
    30.         BKL_LOCK();
    31.         
    32.         read_tsc_64(&tsc);

    33.         bkl_ticks[cpu] = add64(bkl_ticks[cpu], sub64(tsc, bkl_tsc));
    34.         bkl_tries[cpu]++;
    35.         bkl_succ[cpu] += !(!(succ == 0));

    36.         p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
    37.     }
    38. #else
    39.     read_tsc_64(&tsc);
    40.     p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
    41. #endif
    42.     
    43.     tsc_delta = sub64(tsc, *__tsc_ctr_switch);

    44.     if(kbill_ipc) {
    45.         kbill_ipc->p_kipc_cycles =
    46.             add64(kbill_ipc->p_kipc_cycles, tsc_delta);
    47.         kbill_ipc = NULL;
    48.     }

    49.     if(kbill_kcall) {
    50.         kbill_kcall->p_kcall_cycles =
    51.             add64(kbill_kcall->p_kcall_cycles, tsc_delta);
    52.         kbill_kcall = NULL;
    53.     }

    54.     /*
    55.      * deduct the just consumed cpu cycles from the cpu time left for this
    56.      * process during its current quantum. Skip IDLE and other pseudo kernel
    57.      * tasks
    58.      */
    59.     if (p->p_endpoint >= 0) {
    60. #if DEBUG_RACE
    61.         make_zero64(p->p_cpu_time_left);
    62. #else
    63.         /* if (tsc_delta < p->p_cpu_time_left) in 64bit */
    64.         if (ex64hi(tsc_delta) < ex64hi(p->p_cpu_time_left) ||
    65.                 (ex64hi(tsc_delta) == ex64hi(p->p_cpu_time_left) &&
    66.                  ex64lo(tsc_delta) < ex64lo(p->p_cpu_time_left)))
    67.             p->p_cpu_time_left = sub64(p->p_cpu_time_left, tsc_delta);
    68.         else {
    69.             make_zero64(p->p_cpu_time_left);
    70.         }
    71. #endif
阅读(1601) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~