在trap_init中对SYSCALL_VECTOR(编号0x80)的向量进行初始化。
808 set_system_trap_gate(SYSCALL_VECTOR, &system_call);将system call初始化为trap门,加入到IDT table中,发生中断以后,会跳转到对应system_call的地址去执行后续的中断流程。发生中断到跳转执行中断向量的过程在kernel 中断分析三——中断处理流程有详细解释,本篇只关注system_call的运行过程。
_TIF_ALLWORK_MASK 的定义如下:
144 /* Work to do on any return to user space. */145 #define _TIF_ALLWORK_MASK /146 (_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|/147 _TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME)当以下情况之一发生时,返回用户态之前需要进入syscall_exit_work处理: 1. 当前进程有信号pending 2. 当前进程需要被重新调度 3. 设置了_TIF_SINGLESTEP,restore singlestep on return to user mode 4. got an async TLB fault in kernel 5. callback before returning to user
670 syscall_exit_work: 671 testl $_TIF_WORK_SYSCALL_EXIT, %ecx----------1 672 jz work_pending 673 TRACE_IRQS_ON 674 ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call 675 # schedule() instead 676 movl %esp, %eax 677 call syscall_trace_leave 678 jmp resume_userspace------------------------2 679 END(syscall_exit_work)检测是否有work pending否则开中断然后返回用户态 607 work_pending: 608 testb $_TIF_NEED_RESCHED, %cl -------------1 609 jz work_notifysig -------------2 610 work_resched: -------------3 611 call schedule 612 LOCKDEP_SYS_EXIT 613 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt 614 # setting need_resched or sigpending 615 # between sampling and the iret 616 TRACE_IRQS_OFF 617 movl TI_flags(%ebp), %ecx 618 andl $_TIF_WORK_MASK, %ecx # is there any work to be done other 619 # than syscall tracing? 620 jz restore_all 621 testb $_TIF_NEED_RESCHED, %cl 622 jnz work_resched 623 624 work_notifysig: # deal with pending signals and-------------------4 625 # notify-resume requests 626 #ifdef CONFIG_VM86 627 testl $X86_EFLAGS_VM, PT_EFLAGS(%esp) 628 movl %esp, %eax 629 jne work_notifysig_v86 # returning to kernel-space or 630 # vm86-space 631 1: 632 #else 633 movl %esp, %eax 634 #endif 635 TRACE_IRQS_ON 636 ENABLE_INTERRUPTS(CLBR_NONE) 637 movb PT_CS(%esp), %bl 638 andb $SEGMENT_RPL_MASK, %bl 639 cmpb $USER_RPL, %bl 640 jb resume_kernel 641 xorl %edx, %edx 642 call do_notify_resume -------------------5 643 jmp resume_userspace 644 645 #ifdef CONFIG_VM86 646 ALIGN 647 work_notifysig_v86: 648 pushl_cfi %ecx # save ti_flags for do_notify_resume 649 call save_v86_state # %eax contains pt_regs pointer 650 popl_cfi %ecx 651 movl %eax, %esp 652 jmp 1b 653 #endif 654 END(work_pending)检测_TIF_NEED_RESCHED,若被设置,跳转到work_resched,否则跳转到work_notifysig,进行信号处理调用schedule主动让出CPU处理pending的信号,具体的处理流程在do_notify_resume 中的do_signal整个处理流程用流程图表现得更加直观:
新闻热点
疑难解答