国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

kernel 系統調用----system call

2019-11-06 09:35:13
字體:
來源:轉載
供稿:網友

Init

在trap_init中對SYSCALL_VECTOR(編號0x80)的向量進行初始化。

808 set_system_trap_gate(SYSCALL_VECTOR, &system_call);

將system call初始化為trap門,加入到IDT table中,發生中斷以后,會跳轉到對應system_call的地址去執行后續的中斷流程。發生中斷到跳轉執行中斷向量的過程在kernel 中斷分析三——中斷處理流程有詳細解釋,本篇只關注system_call的運行過程。

ENTRY(system_call)

499 /* 500 * syscall stub including irq exit should be PRotected against kprobes 501 */ 502 .pushsection .kprobes.text, "ax" 503 # system call handler stub 504 ENTRY(system_call) 505 RING0_INT_FRAME # can't unwind into user space anyway 506 ASM_CLAC 507 pushl_cfi %eax # save orig_eax --------------1 508 SAVE_ALL -----------2 509 GET_THREAD_INFO(%ebp) -----------3 510 # system call tracing in Operation / emulation 511 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) ---------4 512 jnz syscall_trace_entry 513 cmpl $(NR_syscalls), %eax 514 jae syscall_badsys 515 syscall_call: --------5 516 call *sys_call_table(,%eax,4) 517 syscall_after_call: --------6 518 movl %eax,PT_EAX(%esp) # store the return value 519 syscall_exit: --------7 520 LOCKDEP_SYS_EXIT 521 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt 522 # setting need_resched or sigpending 523 # between sampling and the iret 524 TRACE_IRQS_OFF 525 movl TI_flags(%ebp), %ecx 526 testl $_TIF_ALLWORK_MASK, %ecx # current->work 527 jne syscall_exit_work 528RING0_INT_FRAME設置esp、eip指向內核態,然后將eax中的系統調用號入棧保存現場,即用戶態的一些寄存器值將thread_info的地址保存到ebp寄存器當前進程是否有被trace,如果有就執行相關的動作保存當時的追蹤信息調用對應的系統調用函數將返回值入棧屏蔽其他中斷。檢測當前進程是否還有工作沒有完成,如果有,那么跳轉到syscall_exit_work然后恢復userspace被壓入棧的寄存器,返回userspace 529 restore_all: 530 TRACE_IRQS_IRET 531 restore_all_notrace: 532 #ifdef CONFIG_X86_ESPFIX32 533 movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS ------------1 534 # Warning: PT_OLDSS(%esp) contains the wrong/random values if we 535 # are returning to the kernel. 536 # See comments in process.c:copy_thread() for details. 537 movb PT_OLDSS(%esp), %ah 538 movb PT_CS(%esp), %al 539 andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax 540 cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax 541 CFI_REMEMBER_STATE 542 je ldt_ss # returning to user-space with LDT SS 543 #endif 544 restore_nocheck: 545 RESTORE_REGS 4 # skip orig_eax/error_code 546 irq_return: 547 INTERRUPT_RETURN ---------- 548 .section .fixup,"ax" 549 ENTRY(iret_exc) 550 pushl $0 # no error code 551 pushl $do_iret_error 552 jmp error_code 553 .previous 554 _ASM_EXTABLE(irq_return,iret_exc) 555 556 #ifdef CONFIG_X86_ESPFIX32 557 CFI_RESTORE_STATE 558 ldt_ss: 559 #ifdef CONFIG_PARAVIRT 560 /* 561 * The kernel can't run on a non-flat stack if paravirt mode 562 * is active. Rather than try to fixup the high bits of 563 * ESP, bypass this code entirely. This may break DOSemu 564 * and/or Wine support in a paravirt VM, although the option 565 * is still available to implement the setting of the high 566 * 16-bits in the INTERRUPT_RETURN paravirt-op. 567 */ 568 cmpl $0, pv_info+PARAVIRT_enabled 569 jne restore_nocheck 570 #endif 571 572 /* 573 * Setup and switch to ESPFIX stack 574 * 575 * We're returning to userspace with a 16 bit stack. The CPU will not 576 * restore the high Word of ESP for us on executing iret... This is an 577 * "official" bug of all the x86-compatible CPUs, which we can work 578 * around to make dosemu and wine happy. We do this by preloading the 579 * high word of ESP with the high word of the userspace ESP while 580 * compensating for the offset by changing to the ESPFIX segment with 581 * a base address that matches for the difference. 582 */ 583 #define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8) 584 mov %esp, %edx /* load kernel esp */ 585 mov PT_OLDESP(%esp), %eax /* load userspace esp */ 586 mov %dx, %ax /* eax: new kernel esp */ 587 sub %eax, %edx /* offset (low word is 0) */ 588 shr $16, %edx 589 mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */ 590 mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */ 591 pushl_cfi $__ESPFIX_SS 592 pushl_cfi %eax /* new kernel esp */ 593 /* Disable interrupts, but do not irqtrace this section: we 594 * will soon execute iret and the tracer was already set to 595 * the irqstate after the iret */ 596 DISABLE_INTERRUPTS(CLBR_EAX) 597 lss (%esp), %esp /* switch to espfix segment */ 598 CFI_ADJUST_CFA_OFFSET -8 599 jmp restore_nocheck 600 #endif 601 CFI_ENDPROC 602 ENDPROC(system_call)

syscall_exit_work

_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

整個處理流程用流程圖表現得更加直觀: 這里寫圖片描述


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 镇江市| 新竹市| 汕尾市| 桂平市| 青铜峡市| 龙门县| 金堂县| 巫山县| 西乌珠穆沁旗| 宁津县| 寿阳县| 安徽省| 罗平县| 花莲市| 泰安市| 伽师县| 察隅县| 株洲县| 阜宁县| 芒康县| 沐川县| 鄢陵县| 武川县| 莱西市| 元阳县| 徐水县| 乌拉特前旗| 繁昌县| 双鸭山市| 确山县| 奉新县| 岳阳县| 沂源县| 锡林郭勒盟| 本溪市| 玉林市| 利川市| 达日县| 涞源县| 明星| 红桥区|