Linux内核0.11 makefile文件说明


#
# if you want the ram-disk device, define this to be the
# size in blocks.
# 如果要使用 RAM 就定义块的大小(注释掉了),这是一个编译时参数,如果定义了在下面会用到。
RAMDISK = #-DRAMDISK=512

AS86    =as86 -0 -a  #8006汇编的编译器和连接器。后面参数分别是:
LD86    =ld86 -0     # -0 生成8086目标程序, -a 生成与gas 和 gld部分兼容的代码。

AS  =gas  #GNU 汇编器和连接器。
LD  =gld
LDFLAGS =-s -x -M  # gld 参数,-s 输出文件中省略所有符号信息, -x 删除所有局部符号, -m 在标准输出设备上打印连接映像
                   #连接映像是指由连接程序程序产生的一种内存地址映像,列出了程序段装到内存中的位置信息。具体指:
                   #1.目标文件及符号信息映射到内存中的位置
                   #2.公告符号如何放置
                   #3.连接中包含的所有文件及其引用的符号

# gcc GNU编译器,引用定义的符号时,需要在前面加上$符号,并用括号把定义的标识符括起来。
CC  =gcc $(RAMDISK)

# -Wall 打印所有警告信息, -O 对代码进行优化   "-f标志" 指定与机器无关的编译标志
# 1. -fstrength-reduce   用于优化循环语句
# 2. -fomit-frame-pointer  指明对无需帧指针(Frame pointer)的函数不要把帧指针保留在寄存器中,可以避免对帧指针的操作和维护。
# 3. -fcombine-regs 指明编译器在组合编译阶段把复制一个寄存器到另一个寄存器的指令组合在一起。
# 4. -mstring-insns linus 在学习gcc时为gcc增加的选项,用于 gcc-1.40 在复制结构等操作时使用386cpu的字符串指令,可以去掉。

CFLAGS  =-Wall -O -fstrength-reduce -fomit-frame-pointer \
-fcombine-regs -mstring-insns

# -nostdinc -Iinclude 不要搜索标准头文件目录中的文件,即不用 /usr/include/目录下的头文件,
# 而是使用 "-I" 选项指定的目录或者是在当前目录里搜索头文件。
CPP =cpp -nostdinc -Iinclude

#
# ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the
# default of /dev/hd6 is used by ‘build‘.
#
# ROOT_DEV 指定在创建内核映像文件时所使用的默认根文件系统所在的设备,可以是软盘、
# /dev/xxx 或者空, 空着时使用默认值 /dev/hd6
#
ROOT_DEV=/dev/hd6

# kernel目录, mm目录,和fs目录所产生的目标代码文件,为了方便引用,用ARCHIVES(归档文件)标识符标书
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o

# 块和字符设备库文件。 ‘.a‘表示该文件是个归档文件,即包含许多可执行二进制代码
#子程序集合的库文件,通常由 GNU的 ar程序生成, ar 是GNU的二进制文件处理程序,用于创建、修改以及从归档文件中抽取文件。
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a

MATH    =kernel/math/math.a  # 数学运算库文件
LIBS    =lib/lib.a  # 由 lib/目录中文件所编译生成的库文件。

#1. make 老式的隐式后缀规则,指示make利用下面的命令将所欲的‘.c‘文件编译生成‘.s‘汇编程序。
#2. 使用 include/ 目录下的头文件,
#3. -S 表示只进行编译,产生与各个C文件对应的汇编文件。默认情况下编译产生的文件名是源文件去掉‘.c‘后再加上‘.s‘后缀。
#4. -o 后面是输出的文件的格式,其中‘$*.s‘(或‘[email protected]‘)是自动目标变量。
#5. ‘$<‘ 代表第一个先决条件,这里即符合条件的‘*.c‘ 文件

#下面有三个规则:
#1.若目标文件是‘.s‘文件,源文件是‘.c‘文件,则使用第一个规则。
#2.若目标文件是‘.o‘文件,源文件是‘.s‘文件,则使用第二个规则。
#3.若目标文件是‘.o‘文件,源文件是‘.c‘文件,则使用第三个规则。

.c.s:
    $(CC) $(CFLAGS) \
    -nostdinc -Iinclude -S -o $*.s $<
.s.o:
    $(AS) -c -o $*.o $<
.c.o:
    $(CC) $(CFLAGS) \
    -nostdinc -Iinclude -c -o $*.o $<

# all 表示makefile所知的最顶层目标,这里是Image文件,这里是引导启动盘映像文件bootimage。
all:    Image

# 冒号后面的文件是生成 Image 文件依赖的4个文件,下一行是生成Image的执行命令
Image: boot/bootsect boot/setup tools/system tools/build
    tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image #生成Image文件的命令
    sync  #使用同步命令迫使缓冲块数据立即写盘并更新超级块。

# disk 目标文件由 Image产生。dd命令:复制一个文件,根据选项进行转换的格式化。
# bs= 表示第一次读/写的字节数。 if= 表示输入的文件。 of= 表示输出到文件。
disk: Image
    dd bs=8192 if=Image of=/dev/PS0  #使用dd命令把Image文件写入/dev/PS0(第一个软盘驱动器)

# 编译生成 tools/build 文件
tools/build: tools/build.c
    $(CC) $(CFLAGS) \
    -o tools/build tools/build.c

# 利用上面给出的 .s.o 规则生成 head.o文件
boot/head.o: boot/head.s

# 编译生成 tools/system文件
tools/system:   boot/head.o init/main.o \
        $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)
    $(LD) $(LDFLAGS) boot/head.o init/main.o \
    $(ARCHIVES) \
    $(DRIVERS) \
    $(MATH) \
    $(LIBS) \
    -o tools/system > System.map

# 生成数学协处理文件,math.a,进入 kernel/math 目录,运行该目录下的makefile。下面的几条命令类似这样。
kernel/math/math.a:
    (cd kernel/math; make)

#生成块设备库文件 blk_drv.a,其中含有可重定位目标文件。
kernel/blk_drv/blk_drv.a:
    (cd kernel/blk_drv; make)

#生成字符设备函数文件 chr_drv.a
kernel/chr_drv/chr_drv.a:
    (cd kernel/chr_drv; make)

#生成内核目标模块 kernel.o
kernel/kernel.o:
    (cd kernel; make)

#生成内存管理模块 mm.o
mm/mm.o:
    (cd mm; make)

#生成文件系统目标模块fs.o
fs/fs.o:
    (cd fs; make)

#生成库函数liba.a
lib/lib.a:
    (cd lib; make)

boot/setup: boot/setup.s                     #这里三行使用8086汇编器和连接器对
    $(AS86) -o boot/setup.o boot/setup.s     #setup.s 文件进行编译生成setup文件
    $(LD86) -s -o boot/setup boot/setup.o    # -s 表示去除目标文件中的符号信息

# 同上,生成 bootsect 磁盘引导块
boot/bootsect:  boot/bootsect.s
    $(AS86) -o boot/bootsect.o boot/bootsect.s
    $(LD86) -s -o boot/bootsect boot/bootsect.o

# 在bootsect.s文本程序开始处添加一行有关system模块文件长度信息,在把system模块
# 加载到内存期间用于指明系统模块的长度。方法是是利用命令获取 system模块的大小,并保存
# 在tmp.s 文件中。cut命令用于剪切字符串,tr用于去掉行尾的回车符。(实际长度+15)/16 用于
# 获得"节"表示的长度信息, 1节 = 16 字节。 这是旧版本(0.01-0.10)在使用,新版本已经不用
# 新版本直接在文件中指明了 system的大小。
tmp.s:  boot/bootsect.s tools/system
    (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
        | cut -c25-31 | tr ‘\012‘ ‘ ‘; echo "+ 15 ) / 16") > tmp.s
    cat boot/bootsect.s >> tmp.s

# 执行 make clean 时执以下命令,删除编译链接生成的文件
# rm 是文件删除命令, -f 表示忽略不存在的文件,并且不显示删除信息。
clean:
    rm -f Image System.map tmp_make core boot/bootsect boot/setup
    rm -f init/*.o tools/system tools/build boot/*.o
    (cd mm;make clean)  #进入 mm/目录,执行该目录下的makefile文件中的clean规则,下面类似。
    (cd fs;make clean)
    (cd kernel;make clean)
    (cd lib;make clean)

#该规则先执行上面的clean规则,然后对 linux/目录进行压缩,生成 backup.Z 压缩文件。
# cd.. 退到Linux的上一级目录,tar cf - linux 表示对tar 目录 进行压缩。
# |compress 表示将压缩文件通过管道操作传递给压缩程序 compres ,并将程序的输出存成 backup.Z文件。
backup: clean
    (cd .. ; tar cf - linux | compress - > backup.Z)
    sync    #使用同步命令迫使缓冲块数据立即写盘并更新超级块。

# 该目标或规则用于产生各个文件之间的依赖关系,创建这些依赖关系是为了让make 目录用来确定是否需要重建一个目标对象。
# 如某个头文件被改动后,make就能通过生成的依赖关系,重新编译与该头文件相关的所有*.c文件。
# 处理过程如下:
# 使用sed字符串编辑程序对makefile进行处理,输出为makefile中删除了‘### Dependencies‘后面的所有行,
# 并生成一个临时文件 tmp_make,然后对指定目录(init/)的每一C文件执行gcc预处理操作。
# -M 告诉预处理程序cpp输出描述目标文件相关性的规则,并且这些规则符合make语法,对每一个源文件,预处理程序
# 会输出一个规则,其结果形式就是相应源文件的目标文件加上其依赖关系,即该源文件中包含的所有头文件列表。
# 然后把预处理结果都添加到临时文件 tmp_make 中,最后再把这个临时文件复制成新的Makefile文件。
# "$$i" 实际上是‘$($i)‘
dep:
    sed ‘/\#\#\# Dependencies/q‘ < Makefile > tmp_make
    (for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
    cp tmp_make Makefile
    (cd fs; make dep)    #对fs目录下的makefile也做同样处理,下面类似。
    (cd kernel; make dep)
    (cd mm; make dep)

# main.o 的依赖文件
### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \
  include/sys/types.h include/sys/times.h include/sys/utsname.h \
  include/utime.h include/time.h include/linux/tty.h include/termios.h \
  include/linux/sched.h include/linux/head.h include/linux/fs.h \
  include/linux/mm.h include/signal.h include/asm/system.h include/asm/io.h \
  include/stddef.h include/stdarg.h include/fcntl.h 

原文地址:https://www.cnblogs.com/ay-a/p/9080013.html

时间: 2024-10-09 20:24:53

Linux内核0.11 makefile文件说明的相关文章

Linux内核0.11 bootsect文件说明

一.总体功能介绍 这是关于Linux-kernel-0.11中boot文件夹下bootsect.s源文件的说明,其中涉及到了一些基础知识可以参考这两篇文章. 操作系统启动过程 软盘相关知识和通过BIOS中断访问软盘 bootsect.s 代码是磁盘引导块程序,存储在磁盘的第一个扇区中(0面0道1扇区),在计算机上电BIOS自检后,BIOS 会吧引导扇区代码bootsect加载到内存0x90000处开并运行. bootsect代码主要完成以下几项工作: 加载从磁盘第二个扇区开始的4个扇区的内容(由

Linux内核源代码情景分析-文件的写

write对应的系统调用是sys_write,代码如下: asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count) { ssize_t ret; struct file * file; ret = -EBADF; file = fget(fd); if (file) { if (file->f_mode & FMODE_WRITE) { struct inode *inode = file-&g

Linux内核0.00-boot.s源代码分析

     1 /*************************************************************************   2  > File Name: boot.s   3  > Author: Linpeng1577   4  > Mail:[email protected] or [email protected]   5  > Created Time: Sun 02 Nov 2014 11:42:53 PM PST   6  

【LINUX网络编程】Makefile文件

<Linux网络编程>(第二版) 第2章的一些读书笔记 ↓ Makefile:在一个含有较多文件的工程中,定义一系列规则来指定编译文件的顺序,可用于管理工程. Makefile指定了工程中的哪些源文件需要编译以及如何编译.需要创建那些库文件以及如何创建这些库文件.如何最后产生我们想要的可执行文件.为工程编写Makefile 的好处是能够使用一行命令来完成“自动化编译”,编译整个工程你所要做的唯一的一件事就是在shell 提示符下输入make命令,整个工程就完全自动编译. 首先来看一下Linux

Linux内核源代码情景分析-文件系统安装后的访问

在Linux内核源代码情景分析-文件系统的安装,一文中,已经调用sudo mount -t ext2 /dev/sdb1 /mnt/sdb,在/mnt/sdb节点上挂载了文件系统,那么我们接下来访问/mnt/sdb/hello.c节点.我们来看一下path_walk的执行有什么不同? int path_walk(const char * name, struct nameidata *nd) { struct dentry *dentry; struct inode *inode; int er

Linux内核3.11的socket busy poll机制避免睡眠切换

Linux的网络协议栈非常独立,上下通过两个接口分别和用户态以及设备相连,也可以看作是北向和南向接口...北向通过socket接口,南向通过qdisc接口(你可以认为是上层的netdev queue,对于接收接口,NAPI的poll队列则是另一个例子),不管是socket还是qdisc,都是基于队列来管理的,也就是说,三个部分是独立的,socket只能看到读写队列,而看不到协议栈本身,socket在读一个数据的时候,它取的是队列里面的数据,至于说这个数据是谁放进去的,它并不知道,是不是协议栈放进

Linux内核系列—11.操作系统开发之ELF格式

ELF文件的结构如下图所示: ELF文件由4部分组成,分别是ELF头(ELF header).程序头表(Program header table).节(Sections)和节头表(Section header table). 实际上,一个文件中不一定包含全部这些内容,而且它们的位置也未必如上图所示这样安排,只有ELF头的位置是固定的,其余各部分的位置.大小等信息由ELF头中的各项值来决定. ELF header的格式如下代码所示: #define EI_NIDENT 16 typedef str

Linux内核源代码情景分析-文件的打开

打开文件的系统调用是open(),在内核中通过sys_open()实现,假设filename是"/usr/local/hello.c",且假设这个文件已经存在,代码如下: asmlinkage long sys_open(const char * filename, int flags, int mode) { char * tmp; int fd, error; #if BITS_PER_LONG != 32 flags |= O_LARGEFILE; #endif tmp = ge

linux kernel 0.11 head

bootsect和setup汇编采用intel的汇编风格,而在head中,此时已经进入32位保护模式,汇编的采用的AT&T的汇编语言,编译器当然也就变成对应的编译和连接器了. 概念: ①关于中断描述符表的详细介绍参阅:http://blog.csdn.net/fwqcuc/article/details/5855460 ②关于控制寄存器(CR0,CR1,CR2,CR3):http://blog.csdn.net/sunnybeike/article/details/6781353 控制寄存器(C