Linux内核源代码分析——Linux内核的入口

Jack:hi,淫龙,在Linux内核的源代码里,有几段汇编代码,那几段代码是负责Linux内核引导的。

我:是的。早期的Linux内核引导代码只有bootsect.s、setup.s、head.s这3个文件,这三个文件都是Linus在1991年左右亲手写的。后来的代码虽然进行了加固,但是原型还是这几个。

Jack:我想弄清楚。这几个汇编代码做了些什么事情。

我:我不能在对话中一句代码一句代码地给你进行注释,这是不现实的。我希望能把你最困惑的知识点解释清楚,起到画龙点睛的作用,而不是手把手地教你它是什么。

Jack:那我提一个最困惑的问题吧。Linux的内核是如何开始执行main()函数的?(在1.0之后?的代码中,所有的Linux入口函数已经改名为start_kernel())。

我:我给你看一段head.s的代码吧。

head.s line 135-141

 

after_page_tables:
	pushl $0		# These are the parameters to main :-)
	pushl $0
	pushl $0
	pushl $L6		# return address for main, if it decides to.
	pushl $_main            # 把main函数的地址压入栈内,等待出栈,指令跳转
	jmp setup_paging        # 跳转到setup_paging标签

 

head.s line 210-218

 

1:	stosl			/* fill pages backwards - more efficient :-) */
	subl $0x1000,%eax
	jge 1b
	xorl %eax,%eax		/* pg_dir is at 0x0000 */
	movl %eax,%cr3		/* cr3 - page directory start */
	movl %cr0,%eax
	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */
	ret			/* this also flushes prefetch-queue */#弹栈,调用_main

关键就在这里:入栈函数地址,ret返回顺便调用_main。

 

Jack:明白了。原来是这样。我再问一个问题。Linux的内核的入口函数为什么可以是start_kernel()——C语言的入口地址不是main()吗?

我:这个问题你可以尝试从汇编的角度来思考。C语言的入口地址不是main()吗?——这个是不一定的。仅仅从C语言的角度来思考,这话是对的。如果从汇编的角度来思考,这话就不对了。

Jack:从汇编的角度来思考C语言?我操。

我:你用gcc -S选项编译一个source file,会生成一个汇编源代码文件。之后才会生成二进制文件。C只是一层皮,真正的骨在于汇编。

Jack:你的意思是,C其实是需要翻译成汇编的,从汇编的层面来思考代码才能把握本质的东西。

我:great。你明白了。


 

posted @ 2013-06-10 20:24  爱生活,爱编程  阅读(8869)  评论(0编辑  收藏  举报