Linux内核完全注释(基于Linux0.11)_笔记_/linux/kernel/system_call.s

说明

前言

在Linux0.11中的系统调用是通过int0x80号中断和eax传递的功能号来调用的
对于所有系统调用的实现函数,内核把它们按照系统调用功能号顺序排列成一张函数指针表,然后在中断int 0x80的中断处理过程中根据用户提供的功能号调用对应系统调用函数进行处理
对于系统调用int0x80的中断处理过程,可以把它看作是一个接口程序,实际上每个系统调用功能的处理过程基本上都是通过调用相应的C函数进行的

作用

本程序主要实现系统调用system_call中断int0x80的入口处理过程以及信号检测处理,同时给出了两个系统功能的底层接口,分别是sys_execve和sys_fork

执行流程

代码解析

# 定义子进程停止或结束的信号
SIG_CHLD	= 17

# 函数返回时,不同寄存器在堆栈中的位置
EAX		= 0x00
EBX		= 0x04
ECX		= 0x08
EDX		= 0x0C
FS		= 0x10
ES		= 0x14
DS		= 0x18
EIP		= 0x1C
CS		= 0x20
EFLAGS		= 0x24
OLDESP		= 0x28
OLDSS		= 0x2C

# 任务结构中变量的偏移值
state	= 0		# 进程状态码
counter	= 4		# 任务运行时间片
priority = 8	# 任务优先级(与数字正相关)
signal	= 12	# 信号位图,每个比特位代表一种信号
sigaction = 16		# 表明sigaction结构长度必须是16byte
blocked = (33*16)	# 受阻信号位图的偏移量

# sigaction结构中的偏移量
sa_handler = 0			# 信号处理过程中的句柄(描述符)
sa_mask = 4				# 信号屏蔽码
sa_flags = 8			# 信号集
sa_restorer = 12		# 恢复函数指针

nr_system_calls = 72	# Linux0.11内核中的系统调用总数

# 申明外部可调用的符号
.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:
	movl $-1,%eax
	iret

# 重新执行调度程序入口
.align 2
reschedule:
	pushl $ret_from_sys_call
	jmp schedule

# 系统调用入口点
.align 2
system_call:
	# 检查系统调用号是否出错
	cmpl $nr_system_calls-1,%eax
	ja bad_sys_call
	
	# 寄存器值保存
	push %ds
	push %es
	push %fs
	
	# 系统调用的参数传递
	pushl %edx
	pushl %ecx
	pushl %ebx

	# 使得ds、es指向内核空间的数据段
	movl $0x10,%edx
	mov %dx,%ds
	mov %dx,%es

	# 使得fs指向局部数据段
	movl $0x17,%edx		# fs points to local data space
	mov %dx,%fs

	# 函数调用,sys_call_table为一个指针数组
	# sys_call_table(,%eax,4)为函数入口
	# sys_call_table(,%eax,4) = sys_call_table + %eax*4
	call sys_call_table(,%eax,4)
	# 将系统调用返回值入栈
	pushl %eax

	# 检查当前进程的时间片是否已经用完,未用完则继续执行,否则进行进程切换
	movl current,%eax
	cmpl $0,state(%eax)		# state
	jne reschedule
	cmpl $0,counter(%eax)		# counter
	je reschedule

# 判断是否为task0,如果是,则不进行信号处理
ret_from_sys_call:
	movl current,%eax		# task[0] cannot have signals
	cmpl task,%eax
	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 %eax
3:	popl %eax
	popl %ebx
	popl %ecx
	popl %edx
	pop %fs
	pop %es
	pop %ds
	iret

# 外部的基于硬件的异常,当协处理器检测到自己发生错误时,就会通过ERROR引脚通知CPU
.align 2
coprocessor_error:
	push %ds
	push %es
	push %fs
	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 %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
	clts				# clear TS so that we can use math
	movl %cr0,%eax
	testl $0x4,%eax			# EM (math emulation bit)
	je math_state_restore
	pushl %ebp
	pushl %esi
	pushl %edi
	call math_emulate
	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 %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

# sys_execve系统调用
.align 2
sys_execve:
	lea EIP(%esp),%eax
	pushl %eax
	call do_execve
	addl $4,%esp
	ret
# sys_fork系统调用
.align 2
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:
	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
	xchgl do_hd,%edx
	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:
	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
	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:
	pushl %eax
	movb $0x20,%al
	outb %al,$0x20
	popl %eax
	iret
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值