本文转自http://blog.sina.com.cn/s/blog_a2dded3d010195hf.html
Nachos系列免责说明:本系列博客所用Nachos源代码及文档均来自互联网,如有侵权,请私信,马上删除。此外,Nachos为高校操作系统实习课程所用,本系列博客只为读者提供思路,以避免浪费不必要的时间,这是博主写这个系列的初衷所在。如果出现作业抄袭现象,博主一概不负责,希望读者实事求是,自己思考!
第一部分 Makefile简介
Linux--Makefile简介下载:http://pan.baidu.com/share/link?shareid=850895810&uk=2822100601
很多window的程序员都不知道makefile这个东东,因为现在主流的IDE都把编译工作自动化完成了,但是作为一个敢于挑战自己工程能力的人,makefile还是要懂。
Makefile类似与一个shell脚本,里面定义了如何编译众多的头文件,源文件。一旦写好,整个工程自动编译,极大提高了开发效率。大多数IDE都有类似的命令,如Delphi的make,Visual C++的nmake和Linux GUN的gmake。
1.回忆一下上一篇博客的cd到nachos/code目录下的make,我们应该是执行了nachos/code下的Makefile,打开此Makefile:
开头的MAKE=gmake是说,以后的gmake都可以用$(MAKE)代替,这样做的好处是跨平台很方便,应为只需要把MAKE=nmake就可以方便移植到visual 平台,对于程序规范化书写,向伯克利那帮大佬们致敬!
接下来的all:是要执行的所有make,我们可以看到执行该make之后其实是对每个代码包里面的.cc或者.h文件里面都做makefile,其中相应的makefile写在相应的代码包中。以Threads为例,code/threads包下面也有makefile,那个makefile才执行了编译code/threads包下面.cc(.h)的操作。在以后的编程中,比如我们只修改了threads代码包下面的.cc或者.h文件,我们就可以直接cd到threads/下面执行make,而不用把整个工程编译。
可能你会觉得奇怪,为什么要写$(MAKE) nachos和$(MAKE) depend两次呢,这是因为在Makefile.common文件中,既有nachos:(其中$(PROGRAM)的值就是nachos) 又有depend:,一次make只能生成一个,如果只是make,那么会自动寻找第一个,所以要写两次,在depend:里面,只要是为了应对不同的机型采取的编译。
2.此外,相信不少人已经注意到了code包下面同时还有Makefile.common,Makefile.dep等文件,我们打开Makefile.dep文件,看到如下:
![Nachos3.4系列-2 <wbr> <wbr>Makefile <wbr>与Nachos中文教程 Nachos3.4系列-2 <wbr> <wbr>Makefile <wbr>与Nachos中文教程](https://i-blog.csdnimg.cn/blog_migrate/05d1fa61796a24e644a931935ecb3362.jpeg)
可见,makefile.dep是为了说明不同的机型所采用的,我所用的处理器就是i386的,所以Host=-DHOST_i386是没错的,如果你的机型是Sun APARC 或者HP,那么把相应的注释除去就好。
再看makefile.common
另外,注意
THREAD_H=../threads/copyright.h\
../threads/list.h\
../threads/scheduler.h\
../threads/synch.h \
../threads/synchlist.h\
../threads/system.h\
../threads/thread.h\
../threads/utility.h\
../machine/interrupt.h\
../machine/sysdep.h\
../machine/stats.h\
../machine/timer.h这种定义方法,这样以后要用到这些头文件时,直接一个THREAD_H就可一代表了,/代表换行符,是为了程序的美观易读。makefile.common的例外一些内容,下面讲解。
3.具体代码Makefile
注意以前定义过的常量,如$(THREAD_H),$(THREAD_C),$(THREAD_O),等等
此外,需要注意的是,DEFINES=-DTHREADS这行的意义在程序中可以用#ifdef的宏命令检测到,这在以后文件系统中有重要应用。
main.o: ../threads/main.cc ../threads/copyright.h ../threads/utility.h \
../threads/bool.h ../machine/sysdep.h ../threads/copyright.h \
/usr/include/stdio.h /usr/include/features.h \
/usr/include/i386-linux-gnu/bits/predefs.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
/usr/lib/gcc/i686-linux-gnu/4.7/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h ../threads/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h /usr/include/string.h \
/usr/include/xlocale.h ../threads/system.h ../threads/thread.h \
../threads/scheduler.h ../threads/list.h ../machine/interrupt.h \
../threads/list.h ../machine/stats.h ../machine/timer.h \
../threads/utility.h
这些代码是说main.o文件的生成以来后面的.h文件
此外,这里的include相当与把后面的makefile里面的内容全部加载到这个文件,也就是要执行Makefile.common和Makefile.dep各一次,
于是我们把剩下没看的Makefile.common看一下:
首先来看
$(PROGRAM): $(OFILES)
$(LD) $(OFILES) $(LDFLAGS) -o $(PROGRAM)
这条语句,这条语句是为了生成可执行文件nachos的,
$(PROGRAM)=nachos
$(OFILES)=$(C_OFILES)+$(S_OFILES)
$(S_OFILES)=switch.o
$(C_OFILES)=$(*.o)这个看是那个包调用的,里面有定义
表示这个包里面的nachos可执行文件依赖于哪些.o文件和.c文件
然后执行$(LD)(=g++) $(OFILES) $(LDFLAGS) -o $(PROGRAM)
这种语句相当与我们平时的编译语句g++ main.o -o main应该很好理解
然后我们再来看看
$(C_OFILES): %.o:
$(CC) $(CFLAGS) -c $<
%表示任意长度的非空字符,%.o文件表示任意.o文件,表明.o文件的生成方式。
$(CC) =g++,$<表示所有依赖目标的挨个值。
为了给lab1线程切换做好准备,要注意一个文件的生成,那就是switch.o的生成方式,这个是采用交叉编译实现的。我们可以看到switch.c这个文件里面写的都是汇编代码,因此需要使用$(INPATH)和$(HOST)的值,这些值什么意思都讲过。
其他包里面的Makefile基本上是和threads包里面是差不多的,再次不再赘述!
在此给出注释过的Makefile的代码包下载:
http://pan.baidu.com/share/link?shareid=2443717544&uk=2822100601
第二部分 Nachos中文教程
想要快速了解nachos如何模拟计算机上真实的操作系统,必须仔细研读Nachos中文教程,建议每个Lab先把Nachos中文读个2~3遍,然后自己思考。
Nachos中文教程分为六个章节,第一第二个章节主要对Nachos整体的介绍,这两章很重要,也是lab1之前必须研读完的。
每个章节,Nachos中文教程都会列出Nachos其中的函数,具体的原理等等信息。
这对于我们了解操作系统理论,养成良好变成习惯以及提升自己工程能力都是非常有帮助的。
下一期,我们将进入Nachos lab1-线程。