- 当用户进程调用fork时,-》\lib\libc\syscall\fork.S中去执行,
点击(此处)折叠或打开
- #include <machine/asm.h>
- IMPORT(_fork)
- ENTRY(fork)
- jmp _C_LABEL(_fork)
- #include <machine/asm.h>
- -》\lib\libc\posix\_fork.c
点击(此处)折叠或打开
- #include <lib.h>
- #define fork _fork
- #include <unistd.h>
- PUBLIC pid_t fork()
- {
- message m;
- return(_syscall(PM_PROC_NR, FORK, &m));
- }
- #include <lib.h>
- -》\lib\nbsd_libc\sys-minix\syscall.c
点击(此处)折叠或打开
- #include <sys/cdefs.h>
- #include <lib.h>
- #include "namespace.h"
- #ifdef __weak_alias
- __weak_alias(syscall, _syscall)
- #endif
- int _syscall(endpoint_t who, int syscallnr, message *msgptr)
- {
- int status;
- msgptr->m_type = syscallnr;
- status = _sendrec(who, msgptr);
- if (status != 0) {
- /* 'sendrec' itself failed. */
- /* XXX - strerror doesn't know all the codes */
- msgptr->m_type = status;
- }
- if (msgptr->m_type < 0) {
- errno = -msgptr->m_type;
- return(-1);
- }
- return(msgptr->m_type);
- }
- #include <sys/cdefs.h>
- -》\lib\nbsd_libc\arch\i386\sys-minix\_ipc.S
点击(此处)折叠或打开
- #include <minix/ipcconst.h>
- #include <machine/asm.h>
- IPCVEC = 33 /* ipc trap to kernel */
- KERVEC = 32 /* syscall trap to kernel */
- SRC_DST = 8 /* source/ destination process */
- MESSAGE = 12 /* message pointer */
- STATUS = 16 /* status pointer */
- /**========================================================================* */
- /* IPC assembly routines * */
- /**========================================================================* */
- /* all message passing routines save ebx, but destroy eax and ecx. */
- ENTRY(_send)
- push %ebp
- movl %esp, %ebp
- push %ebx
- movl SRC_DST(%ebp), %eax /* eax = dest-src */
- movl MESSAGE(%ebp), %ebx /* ebx = message pointer */
- movl $SEND, %ecx /* _send(dest, ptr) */
- int $IPCVEC /* trap to the kernel */
- pop %ebx
- pop %ebp
- ret
- ENTRY(_receive)
- push %ebp
- movl %esp, %ebp
- push %ebx
- movl SRC_DST(%ebp), %eax /* eax = dest-src */
- movl MESSAGE(%ebp), %ebx /* ebx = message pointer */
- movl $RECEIVE, %ecx /* _receive(src, ptr) */
- int $IPCVEC /* trap to the kernel */
- movl STATUS(%ebp), %ecx /* ecx = status pointer */
- movl %ebx, (%ecx)
- pop %ebx
- pop %ebp
- ret
- ENTRY(_sendrec)
- push %ebp
- movl %esp, %ebp
- push %ebx
- movl SRC_DST(%ebp), %eax /* eax = dest-src */
- movl MESSAGE(%ebp), %ebx /* ebx = message pointer */
- movl $SENDREC, %ecx /* _sendrec(srcdest, ptr) */
- int $IPCVEC /* trap to the kernel */
- pop %ebx
- pop %ebp
- ret
- ENTRY(_notify)
- push %ebp
- movl %esp, %ebp
- push %ebx
- movl SRC_DST(%ebp), %eax /* eax = destination */
- movl $NOTIFY, %ecx /* _notify(srcdst) */
- int $IPCVEC /* trap to the kernel */
- pop %ebx
- pop %ebp
- ret
- ENTRY(_sendnb)
- push %ebp
- movl %esp, %ebp
- push %ebx
- movl SRC_DST(%ebp), %eax /* eax = dest-src */
- movl MESSAGE(%ebp), %ebx /* ebx = message pointer */
- movl $SENDNB, %ecx /* _sendnb(dest, ptr) */
- int $IPCVEC /* trap to the kernel */
- pop %ebx
- pop %ebp
- ret
- ENTRY(_do_kernel_call)
- /* pass the message pointer to kernel in the %eax register */
- movl 4(%esp), %eax
- int $KERVEC
- ret
- #include <minix/ipcconst.h>
- 语句(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。
点击(此处)折叠或打开
- /* Build descriptors for interrupt gates in IDT. */
- PUBLIC void idt_init(void)
- {
- struct gate_table_s gate_table[] = {
- { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE },
- { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE },
- { nmi, NMI_VECTOR, INTR_PRIVILEGE },
- { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE },
- { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE },
- { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE },
- { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE },
- { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE },
- { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE },
- { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE },
- { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE },
- { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE },
- { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE },
- { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
- { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
- { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
- { alignment_check, ALIGNMENT_CHECK_VECTOR, INTR_PRIVILEGE },
- { machine_check, MACHINE_CHECK_VECTOR, INTR_PRIVILEGE },
- { simd_exception, SIMD_EXCEPTION_VECTOR, INTR_PRIVILEGE },
- { ipc_entry, IPC_VECTOR, USER_PRIVILEGE },
- { kernel_call_entry, KERN_CALL_VECTOR, USER_PRIVILEGE },
- { NULL, 0, 0}
- };
- idt_copy_vectors(gate_table);
- idt_copy_vectors(gate_table_pic);
- }
- /* Build descriptors for interrupt gates in IDT. */
- -》\kernel\arch\i386\mpx.S
点击(此处)折叠或打开
- /*
- * IPC is only from a process to kernel
- */
- ENTRY(ipc_entry)
- SAVE_PROCESS_CTX(0)
- /* save the pointer to the current process */
- push %ebp
- /*
- * pass the syscall arguments from userspace to the handler.
- * SAVE_PROCESS_CTX() does not clobber these registers, they are still
- * set as the userspace have set them
- */
- push %ebx
- push %eax
- push %ecx
- /* stop user process cycles */
- push %ebp
- /* for stack trace */
- movl $0, %ebp
- call _C_LABEL(context_stop)
- add $4, %esp
- call _C_LABEL(do_ipc)
- /* restore the current process pointer and save the return value */
- add $3 * 4, %esp
- pop %esi
- mov %eax, AXREG(%esi)
- jmp _C_LABEL(switch_to_user)
- /*
- -》\kernel\arch\i386\arch_clock.c
点击(此处)折叠或打开
- PUBLIC void context_stop(struct proc * p)
- {
- u64_t tsc, tsc_delta;
- u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
- #ifdef CONFIG_SMP
- unsigned cpu = cpuid;
- /*
- * This function is called only if we switch from kernel to user or idle
- * or back. Therefore this is a perfect location to place the big kernel
- * lock which will hopefully disappear soon.
- *
- * If we stop accounting for KERNEL we must unlock the BKL. If account
- * for IDLE we must not hold the lock
- */
- if (p == proc_addr(KERNEL)) {
- u64_t tmp;
- read_tsc_64(&tsc);
- tmp = sub64(tsc, *__tsc_ctr_switch);
- kernel_ticks[cpu] = add64(kernel_ticks[cpu], tmp);
- p->p_cycles = add64(p->p_cycles, tmp);
- BKL_UNLOCK();
- } else {
- u64_t bkl_tsc;
- atomic_t succ;
-
- read_tsc_64(&bkl_tsc);
- /* this only gives a good estimate */
- succ = big_kernel_lock.val;
-
- BKL_LOCK();
-
- read_tsc_64(&tsc);
- bkl_ticks[cpu] = add64(bkl_ticks[cpu], sub64(tsc, bkl_tsc));
- bkl_tries[cpu]++;
- bkl_succ[cpu] += !(!(succ == 0));
- p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
- }
- #else
- read_tsc_64(&tsc);
- p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
- #endif
-
- tsc_delta = sub64(tsc, *__tsc_ctr_switch);
- if(kbill_ipc) {
- kbill_ipc->p_kipc_cycles =
- add64(kbill_ipc->p_kipc_cycles, tsc_delta);
- kbill_ipc = NULL;
- }
- if(kbill_kcall) {
- kbill_kcall->p_kcall_cycles =
- add64(kbill_kcall->p_kcall_cycles, tsc_delta);
- kbill_kcall = NULL;
- }
- /*
- * deduct the just consumed cpu cycles from the cpu time left for this
- * process during its current quantum. Skip IDLE and other pseudo kernel
- * tasks
- */
- if (p->p_endpoint >= 0) {
- #if DEBUG_RACE
- make_zero64(p->p_cpu_time_left);
- #else
- /* if (tsc_delta < p->p_cpu_time_left) in 64bit */
- if (ex64hi(tsc_delta) < ex64hi(p->p_cpu_time_left) ||
- (ex64hi(tsc_delta) == ex64hi(p->p_cpu_time_left) &&
- ex64lo(tsc_delta) < ex64lo(p->p_cpu_time_left)))
- p->p_cpu_time_left = sub64(p->p_cpu_time_left, tsc_delta);
- else {
- make_zero64(p->p_cpu_time_left);
- }
- #endif
- PUBLIC void context_stop(struct proc * p)