App下載

Linux之父27年前寫的一段代碼

猿友 2018-01-24 18:05:34 瀏覽數(shù) (29387)
反饋

有程序員網(wǎng)友曝出了萊納斯?托瓦爾茲(Linus Torvalds) 1991 年公開的 Linux 源代碼,這引起了 W3Cschool 的注意,可以研究一下這位大神的代碼:

源碼:

/

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-interrupt is 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':

0(%esp) - %eax
4(%esp) - %ebx
8(%esp) - %ecx
C(%esp) - %edx
10(%esp) - %fs
14(%esp) - %es
18(%esp) - %ds
1C(%esp) - %eip
20(%esp) - %cs
24(%esp) - %eflags
28(%esp) - %oldesp
2C(%esp) - %oldss
/

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 # these are offsets into the task-struct.
counter = 4
priority = 8
signal = 12
restorer = 16 # address of info-restorer
sig_fn = 20 # table of 32 signal addresses

nr_system_calls = 67

.globl _system_call,_sys_fork,_timer_interrupt,_hd_interrupt,_sys_execve

.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 # push %ebx,%ecx,%edx as parameters
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
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
ret_from_sys_call:
movl _current,%eax # task[0] cannot have signals
cmpl _task,%eax
je 3f
movl CS(%esp),%ebx # was old code segment supervisor
testl $3,%ebx # mode? If so - don't check signals
je 3f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 3f
2: movl signal(%eax),%ebx # signals (bitmap, 32 signals)
bsfl %ebx,%ecx # %ecx is signal nr, return if none
je 3f
btrl %ecx,%ebx # clear it
movl %ebx,signal(%eax)
movl sig_fn(%eax,%ecx,4),%ebx # %ebx is signal handler address
cmpl $1,%ebx
jb default_signal # 0 is default signal handler - exit
je 2b # 1 is ignore - find next signal
movl $0,sig_fn(%eax,%ecx,4) # reset signal handler address
incl %ecx
xchgl %ebx,EIP(%esp) # put new return address on stack
subl $28,OLDESP(%esp)
movl OLDESP(%esp),%edx # push old return address on stack
pushl %eax # but first check that it's ok.
pushl %ecx
pushl $28
pushl %edx
call _verify_area
popl %edx
addl $4,%esp
popl %ecx
popl %eax
movl restorer(%eax),%eax
movl %eax,%fs:(%edx) # flag/reg restorer
movl %ecx,%fs:4(%edx) # signal nr
movl EAX(%esp),%eax
movl %eax,%fs:8(%edx) # old eax
movl ECX(%esp),%eax
movl %eax,%fs:12(%edx) # old ecx
movl EDX(%esp),%eax
movl %eax,%fs:16(%edx) # old edx
movl EFLAGS(%esp),%eax
movl %eax,%fs:20(%edx) # old eflags
movl %ebx,%fs:24(%edx) # old return addr
3: popl %eax
popl %ebx
popl %ecx
popl %edx
pop %fs
pop %es
pop %ds
iret

default_signal:
incl %ecx
cmpl $SIG_CHLD,%ecx
je 2b
pushl %ecx
call _do_exit # remember to set bit 7 when dumping core
addl $4,%esp
jmp 3b

.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

.align 2
_sys_execve:
lea EIP(%esp),%eax
pushl %eax
call _do_execve
addl $4,%esp
ret

.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,$0x20 # EOI to interrupt controller #1
jmp 1f # give port chance to breathe
1: jmp 1f
1: outb %al,$0xA0 # same to controller #2
movl _do_hd,%eax
testl %eax,%eax
jne 1f
movl $_unexpected_hd_interrupt,%eax
1: call %eax # "interesting" way of handling intr.
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret

Linux之父

托瓦爾茲 1969 年 12 月 28 日出生于芬蘭赫爾辛基市,父母都是記者。他從小就對計算機感興趣。1988 年他進入赫爾辛基大學學習,專業(yè)為計算機科學。1991 年,他購買了一臺屬于自己的 PC 機。赫爾辛基大學當時采用Unix操作系統(tǒng),托瓦爾茲覺得該產(chǎn)品性能不盡如人意,于是就嘗試著自己編寫一款操作系統(tǒng)內(nèi)核,這就是 Linux 操作系統(tǒng)來源。

1997 年至 2003 年,托瓦爾茲在美國加州全美達(Transmeta)公司工作。2003 年 7 月,他加盟“開放源代碼開發(fā)實驗室”(OSDL),以全力開發(fā) Linux 內(nèi)核。后來 OSDL 與“免費標準集團”(FSG)合并成立了 Linux 基金會。托瓦爾茲如今仍在 Linux 基金會工作。與其他 IT 明星人物所不同的是,托瓦茲平常行事較為低調(diào),一般很少在公開場合評論商業(yè)競爭對手產(chǎn)品的好壞。


學編程,從w3cschool開始,w3cschool推出的編程微課,能夠幫助新手更快地學會一門語言,采用的是一題一練,邊學邊練的高效學習模式!

有興趣的童鞋的嘗試一下!W3Cschool編程微課


5 人點贊