linux-sys_call.s

/*
*  linux/kernel/system_call.s
*                                !--int 0x80中断调用,内核提供的各种功能服务
*  (C) 1991  Linus Torvalds
*/
/*
*  system_call.s  contains the system-call low-level handling routines.
* This also contains the timer-interrupt handler, as some of the code is
* the same. The hd- and flopppy-interrupts are also here.
*
* NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call. Ordinary interrupts
* don't handle signal-recognition, as that would clutter them up totally
* unnecessarily.
*
* Stack layout in 'ret_from_system_call':
*                                /*系统调用返回ret_froom_system_call时堆栈的内容*/
*     0(%esp) - %eax
*     4(%esp) - %ebx
*     8(%esp) - %ecx
*     C(%esp) - %edx
*    10(%esp) - original %eax    (-1 if not system call)
*    14(%esp) - %fs
*    18(%esp) - %es
*    1C(%esp) - %ds
*    20(%esp) - %eip
*    24(%esp) - %cs
*    28(%esp) - %eflags
*    2C(%esp) - %oldesp
*    30(%esp) - %oldss
*/
SIG_CHLD    = 17            !--子进程结束信号
EAX        = 0x00                !--堆栈中各个寄存器的偏移值
EBX        = 0x04
ECX        = 0x08
EDX        = 0x0C
ORIG_EAX    = 0x10
FS        = 0x14
ES        = 0x18
DS        = 0x1C
EIP        = 0x20                !--CPU自动入栈
CS        = 0x24
EFLAGS        = 0x28
OLDESP        = 0x2C
OLDSS        = 0x30
state    = 0        # these are offsets into the task-struct.
counter    = 4        !--------------结构体struct task
priority = 8
signal    = 12
sigaction = 16        # MUST be 16 (=len of sigaction)
blocked = (33*16)
# offsets within sigaction        !--结构体sigaction中的偏移量
sa_handler = 0
sa_mask = 4
sa_flags = 8
sa_restorer = 12
nr_system_calls = 82
ENOSYS = 38
/*
* Ok, I get parallel printer interrupts while using the floppy for some
* strange reason. Urgel. Now I just ignore them.
*/
.globl _system_call,_sys_fork,_timer_interrupt,_sys_execve
.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
.globl _device_not_available, _coprocessor_error
.align 2
bad_sys_call:                !--出错信息
    pushl $-ENOSYS
    jmp ret_from_sys_call
.align 2
reschedule:                    !--调用调度函数
    pushl $ret_from_sys_call
    jmp _schedule
.align 2
_system_call:                !--linux系统调用入口
    push %ds
    push %es
    push %fs
    pushl %eax        # save the orig_eax
    pushl %edx        
    pushl %ecx        # push %ebx,%ecx,%edx as parameters        !--3个参数
    pushl %ebx        # to the system call
    movl $0x10,%edx        # set up ds,es to kernel space
    mov %dx,%ds
    mov %dx,%es
    movl $0x17,%edx        # fs points to local data space
    mov %dx,%fs
    cmpl _NR_syscalls,%eax                    !--调用号是否超出范围?
    jae bad_sys_call                        !--如果超出就跳转
    call _sys_call_table(,%eax,4)            !--_sys_call_table[]指针数组,设置了内核82个系统调用C处理函数的地址
    pushl %eax                                !--系统调用返回值入栈
2:
    movl _current,%eax                        !--如果当前进程没就绪/时间片用完,这调度其它程序执行
    cmpl $0,state(%eax)        # state
    jne reschedule
    cmpl $0,counter(%eax)        # counter
    je reschedule
ret_from_sys_call:                            !--判断是否是任务0,是则退出
    movl _current,%eax
    cmpl _task,%eax            # task[0] cannot have signals
    je 3f
    cmpw $0x0f,CS(%esp)        # was old code segment supervisor ?        !--是否是用户态,若为内核态,则退出
    jne 3f                                                            !--因为内核态不可抢占
    cmpw $0x17,OLDSS(%esp)        # was stack segment = 0x17 ?
    jne 3f
    movl signal(%eax),%ebx                    !--处理当前任务中的信号
    movl blocked(%eax),%ecx
    notl %ecx
    andl %ebx,%ecx
    bsfl %ecx,%ecx
    je 3f
    btrl %ecx,%ebx
    movl %ebx,signal(%eax)
    incl %ecx
    pushl %ecx
    call _do_signal
    popl %ecx
    testl %eax, %eax
    jne 2b        # see if we need to switch tasks, or do more signals
3:    popl %eax                                !--按100行的入栈的返回值返回
    popl %ebx
    popl %ecx
    popl %edx
    addl $4, %esp    # skip orig_eax
    pop %fs
    pop %es
    pop %ds
    iret
.align 2
_coprocessor_error:                            !--处理器错误中断
    push %ds
    push %es
    push %fs
    pushl $-1        # fill in -1 for orig_eax
    pushl %edx
    pushl %ecx
    pushl %ebx
    pushl %eax
    movl $0x10,%eax
    mov %ax,%ds
    mov %ax,%es
    movl $0x17,%eax
    mov %ax,%fs
    pushl $ret_from_sys_call
    jmp _math_error
.align 2
_device_not_available:                        !--设备不存在或协处理器不存在
    push %ds
    push %es
    push %fs
    pushl $-1        # fill in -1 for orig_eax
    pushl %edx
    pushl %ecx
    pushl %ebx
    pushl %eax
    movl $0x10,%eax
    mov %ax,%ds
    mov %ax,%es
    movl $0x17,%eax
    mov %ax,%fs
    pushl $ret_from_sys_call                !--清CR0中任务已交换标志TS,并取CR0值
    clts                # clear TS so that we can use math
    movl %cr0,%eax
    testl $0x4,%eax            # EM (math emulation bit)
    je _math_state_restore                    !--数学仿真程序math_emulate()
    pushl %ebp
    pushl %esi
    pushl %edi
    pushl $0        # temporary storage for ORIG_EIP
    call _math_emulate
    addl $4,%esp
    popl %edi
    popl %esi
    popl %ebp
    ret
.align 2
_timer_interrupt:                            !--时钟中断处理程序
    push %ds        # save ds,es and put kernel data space
    push %es        # into them. %fs is used by _system_call
    push %fs
    pushl $-1        # fill in -1 for orig_eax
    pushl %edx        # we save %eax,%ecx,%edx as gcc doesn't
    pushl %ecx        # save those across function calls. %ebx
    pushl %ebx        # is saved as we use that in ret_sys_call
    pushl %eax
    movl $0x10,%eax
    mov %ax,%ds
    mov %ax,%es
    movl $0x17,%eax
    mov %ax,%fs
    incl _jiffies
    movb $0x20,%al        # EOI to interrupt controller #1
    outb %al,$0x20
    movl CS(%esp),%eax
    andl $3,%eax        # %eax is CPL (0 or 3, 0=supervisor)
    pushl %eax
    call _do_timer        # 'do_timer(long CPL)' does everything from
    addl $4,%esp        # task switching to accounting ...
    jmp ret_from_sys_call
.align 2
_sys_execve:                                !--sys_execve()系统调用
    lea EIP(%esp),%eax
    pushl %eax
    call _do_execve
    addl $4,%esp
    ret
.align 2
_sys_fork:                                    !--sys_fork()调用
    call _find_empty_process
    testl %eax,%eax
    js 1f
    push %gs
    pushl %esi
    pushl %edi
    pushl %ebp
    pushl %eax
    call _copy_process
    addl $20,%esp
1:    ret
_hd_interrupt:                                !--int46,硬盘中断处理程序
    pushl %eax
    pushl %ecx
    pushl %edx
    push %ds
    push %es
    push %fs
    movl $0x10,%eax
    mov %ax,%ds
    mov %ax,%es
    movl $0x17,%eax
    mov %ax,%fs
    movb $0x20,%al
    outb %al,$0xA0        # EOI to interrupt controller #1
    jmp 1f            # give port chance to breathe
1:    jmp 1f
1:    xorl %edx,%edx
    movl %edx,_hd_timeout
    xchgl _do_hd,%edx                        !--do_hd函数指针,指向read_init()或write_init();
    testl %edx,%edx
    jne 1f
    movl $_unexpected_hd_interrupt,%edx
1:    outb %al,$0x20
    call *%edx        # "interesting" way of handling intr.
    pop %fs
    pop %es
    pop %ds
    popl %edx
    popl %ecx
    popl %eax
    iret
_floppy_interrupt:                            !--int38,软盘中断处理程序
    pushl %eax
    pushl %ecx
    pushl %edx
    push %ds
    push %es
    push %fs
    movl $0x10,%eax
    mov %ax,%ds
    mov %ax,%es
    movl $0x17,%eax
    mov %ax,%fs
    movb $0x20,%al
    outb %al,$0x20        # EOI to interrupt controller #1
    xorl %eax,%eax
    xchgl _do_floppy,%eax                    !--do_floppy函数指针
    testl %eax,%eax
    jne 1f
    movl $_unexpected_floppy_interrupt,%eax
1:    call *%eax        # "interesting" way of handling intr.
    pop %fs
    pop %es
    pop %ds
    popl %edx
    popl %ecx
    popl %eax
    iret
_parallel_interrupt:                        !--int39,并行口中断处理程序
    pushl %eax
    movb $0x20,%al
    outb %al,$0x20
    popl %eax
    iret
|xGv00|fcc8d4de8197f69fde70263fb4d52380

你可能感兴趣的:(linux-sys_call.s)