1.Linux
内核源码结构:
内核源码中主要包含以下子目录:
arch :包含了与体系结构相关的代码
对应于每一个支持的体系结构,有一个相应的子目录如 i386 、 arm 、 alpha 等。
其每个体系结构子目录下包含几个主要的子目录:
kernel :包含与体系结构相关的内核代码
mm : 包含与体系结构相关的内存管理代码
lib : 包含与体系结构相关的库代码
documentation :包含内核的文档
drivers :包含设备驱动代码。每类设备有相应的子目录,如 char 、 block 、 net 等
fs : 包含文件系统的代码。每个支持的文件系统有相应的子目录,如 ext2 、 proc 等
include :内核头文件,对每一种体系结构,分别有相应的子目录。
init : 包含内核初始化代码
lib : 包含内核的库代码
mm :包含内存管理代码
kernel :包含内核管理代码
net :包含网络部分的代码
2. 系统引导的过程
在 pc 机上系统启动过程:
系统加电以后 bois 对系统完成监测设置后将控制权交给硬盘上 MBR 中的 BootLoader 在这里即是 lilo 或 grub 等。
BootLoader 将操作系统代码调入内存,然后将控制权交给 arch/i386/boot 中的 Setup.S 这段程序。
Setup.S 这段程序在 386 实模式下对系统进行基本的检测和设置后转入保护模式把控制权交给 Head.S
Head.S 建立内存管理和中断管理的框架后调用 init/main.c 中的 start_kernel ()函数在 start_kernel 执行完成后用户就可以登录和使用 linux 了。 Start_kernel() 函数在 init/main.c 中定义。
Start_kernel 的流程中的主要步骤:
setup_arch(&command_line); 用于和处理器、内存等最基本的硬件相关部分的初始化。 在 arch/i386/kernel/setup.c 中定义;
parse_options(command_line); 把启动时得到的参数从命令行的字符串中分离出来并赋给相应的变量。在 init/main.c 中定义;
trap_init(); 对中断向量表进行初始化。在 arch/i386/kernel/trap.c 中定义;
init_IRQ(); 与中断有关的初始化, 在 arch/i386/kernel/i8259.c 中定义;
sched_init(); 进程调度初始化。 在 kernel/sched.c 中定义;
softirq_init(); 在 kernel/softirq.c 中定义;
time_init(); 时间部分初始化。 在 arch/i386/kernel/time.c 中定义;
console_init(); 对终端初始化。 在 drivers/char/tty_io.c 中定义;
buffer_init(mempages); 对用于指示块缓存的 buff free list 初始化。 在 fs/buffer.c 中定义;
mem_init(); 内存管理初始化。 在 arch/i386/mm/init.c 中定义;
rest_init(); 此函数中调用
kernel_thread(init,NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL) 函数时会调用 init/main.c 中的 init() 函数在 init() 函数中将会建立 dbflush 、 kswapd 两个新的内核线程。初始化 tty1 设备。寻找 /etc/init 或 /sbin/init 或 /bin/init 来建立一个 init 进程。
Init 进程根据 /etc/inittab 文件进行文件系统检查、启动系统守护进程为联机终端建立 getty 进程,执行 /etc/rc 下的命令文件。
此后 getty 会在终端上显示 login 提示符,以等待用户登录。
3. 使用 make 建立内核
1. 使用 make menuconfig 命令:
使用以下编译选项 :
Processor type and features --->
(Pentium-Pro/Celeron/Pentium-II) Processor family
(3GB) Maximum Virtual Memory
General setup --->
(ELF) Kernel core (/proc/kcore) format
内核源码中主要包含以下子目录:
arch :包含了与体系结构相关的代码
对应于每一个支持的体系结构,有一个相应的子目录如 i386 、 arm 、 alpha 等。
其每个体系结构子目录下包含几个主要的子目录:
kernel :包含与体系结构相关的内核代码
mm : 包含与体系结构相关的内存管理代码
lib : 包含与体系结构相关的库代码
documentation :包含内核的文档
drivers :包含设备驱动代码。每类设备有相应的子目录,如 char 、 block 、 net 等
fs : 包含文件系统的代码。每个支持的文件系统有相应的子目录,如 ext2 、 proc 等
include :内核头文件,对每一种体系结构,分别有相应的子目录。
init : 包含内核初始化代码
lib : 包含内核的库代码
mm :包含内存管理代码
kernel :包含内核管理代码
net :包含网络部分的代码
2. 系统引导的过程
在 pc 机上系统启动过程:
系统加电以后 bois 对系统完成监测设置后将控制权交给硬盘上 MBR 中的 BootLoader 在这里即是 lilo 或 grub 等。
BootLoader 将操作系统代码调入内存,然后将控制权交给 arch/i386/boot 中的 Setup.S 这段程序。
Setup.S 这段程序在 386 实模式下对系统进行基本的检测和设置后转入保护模式把控制权交给 Head.S
Head.S 建立内存管理和中断管理的框架后调用 init/main.c 中的 start_kernel ()函数在 start_kernel 执行完成后用户就可以登录和使用 linux 了。 Start_kernel() 函数在 init/main.c 中定义。
Start_kernel 的流程中的主要步骤:
setup_arch(&command_line); 用于和处理器、内存等最基本的硬件相关部分的初始化。 在 arch/i386/kernel/setup.c 中定义;
parse_options(command_line); 把启动时得到的参数从命令行的字符串中分离出来并赋给相应的变量。在 init/main.c 中定义;
trap_init(); 对中断向量表进行初始化。在 arch/i386/kernel/trap.c 中定义;
init_IRQ(); 与中断有关的初始化, 在 arch/i386/kernel/i8259.c 中定义;
sched_init(); 进程调度初始化。 在 kernel/sched.c 中定义;
softirq_init(); 在 kernel/softirq.c 中定义;
time_init(); 时间部分初始化。 在 arch/i386/kernel/time.c 中定义;
console_init(); 对终端初始化。 在 drivers/char/tty_io.c 中定义;
buffer_init(mempages); 对用于指示块缓存的 buff free list 初始化。 在 fs/buffer.c 中定义;
mem_init(); 内存管理初始化。 在 arch/i386/mm/init.c 中定义;
rest_init(); 此函数中调用
kernel_thread(init,NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL) 函数时会调用 init/main.c 中的 init() 函数在 init() 函数中将会建立 dbflush 、 kswapd 两个新的内核线程。初始化 tty1 设备。寻找 /etc/init 或 /sbin/init 或 /bin/init 来建立一个 init 进程。
Init 进程根据 /etc/inittab 文件进行文件系统检查、启动系统守护进程为联机终端建立 getty 进程,执行 /etc/rc 下的命令文件。
此后 getty 会在终端上显示 login 提示符,以等待用户登录。
3. 使用 make 建立内核
1. 使用 make menuconfig 命令:
使用以下编译选项 :
Processor type and features --->
(Pentium-Pro/Celeron/Pentium-II) Processor family
(3GB) Maximum Virtual Memory
General setup --->
(ELF) Kernel core (/proc/kcore) format
·
Kernel support for ELF binaries
File systems --->
File systems --->
·
/proc file system support
·
Second extended fs support
ATA/IDE/MFM/RLL support --->
ATA/IDE/MFM/RLL support --->
·
ATA/IDE/MFM/RLL support
·
Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
·
Include IDE/ATA-2 DISK support
Character devices --->
Character devices --->
·
Virtual terminal
Console drivers --->
Console drivers --->
·
VGA text console
生成内核 bzImage 大小为 309892 byte;
此内核可在 pc 上成功引导系统
此命令生成一个文件 .config 其中根据你在 menuconfig 中的选择定义了相应的变量。在 Makefile 文件中将会包含这个文件。
2. 使用 make dep 命令 建立依赖关系。
3. 使用 make bzImage 命令建立内核。
如设置正确将在 arch/i386/boot/ 目录下生成内核 bzImage 文件
4.make bzImage 的流程简单说明
当我们使用 make 命令时, make 程序将首先找到当前目录下的 Makefile 文件。根据 Makefile 文件的语法进行处理。
在主 Makefile 文件中包含了 arch/i386/Makefile 我们 make 的目标 bzImage 即在该文件中定:
bzImage: vmlinux
@$(MAKEBOOT) bzImage # 此命令将解释为: make -C arch/i386/boot bzImage
现在 make 需要先去建立目标 vmlinux 然后再执行 arch/i386/boot/ 目录下的 make bzImae 。我们现在假设 vmlinux 目标已生成,则 arch/i386/boot 目录下的 make 程序将执行如下操作:
tools/build -b bbootsect bsetup compressed/bvmlinux.out ./ bzImage
即将 vmlinux 用 tools/build 工具压缩成目标文件 bzImage (在此过程中,还会构建 build 程序,将 vmlinux 转换成 bvmlinux.out 等,可参考 tools 和 compressed 目录下的 Makefile 文件)。
生成 vmlinux 目标:
在主目录下 Makefile 文件中 vmlinux 生成规则如下:
vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux # 生成 vmlinux
$(NM) vmlinux |grep ?v /(compiled/)/|/(/.o$$/)/|/( [aUw] /)/|/(/./.ng$$/)/|/(LASH[RL]DI/) | sort > System.map # 此命令根据 vmlinux 生成 System.map 文件
在当前设置下此 ld 连接命令被解释为:
ld -m elf_i386 -T /home/arm/linux/arch/i386/vmlinux.lds -e stext arch/i386/kernel/head.o arch/i386/kernel/init_task.o init/main.o init/version.o --start-group arch/i386/kernel/kernel.o arch/i386/mm/mm.o kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o drivers/char/char.o drivers/block/block.o drivers/misc/misc.o drivers/net/net.o drivers/media/media.o drivers/ide/idedriver.o drivers/video/video.o net/network.o /home/arm/linux/arch/i386/lib/lib.a /home/arm/linux/lib/lib.a /home/arm/linux/arch/i386/lib/lib.a --end-group -o vmlinux
即连接程序 ld 将各个 .o 文件连接成目标文件 vmlinux 。
此命令中用到的各个 .o 文件 make 程序会根据 Makefile 文件的规则去自动生成,下面简单介绍一下由 ipc 目录生成 ipc.o 过程:
其 ipc 目录下 Makefile 文件内容如下:
O_TARGET := ipc.o
obj-y := util.o
obj-$(CONFIG_SYSVIPC) += msg.o sem.o shm.o
include $(TOPDIR)/Rules.make # 包含的 Rules.make 文件中为通用的规则;
如我们在 make menuconfig 时选中了 SYSVIPC 选项,则 .config 文件中将定义变量 CONFIG_SYSVIPC=y; 则 obj - y 就等于 util.o msg.o sem.o shm.o ;根据 Rules.make 将四个 .c 文件编译为 .o 文件。再将四个 .o 文件连接成 ipc.o 文件。在我们的当前设置中没有选择 SYSVIPC; 将只使用 util.o 一个文件生成目标 ipc.o ;而 util.o 由 util.c 生成。
当所有需要的 .o 文件生成以后,由 ld 将其连接生成 vmlinux 文件,再将其压缩成我们所需要的内核文件 bzImage 。 Make 程序就执行完了。
生成内核 bzImage 大小为 309892 byte;
此内核可在 pc 上成功引导系统
此命令生成一个文件 .config 其中根据你在 menuconfig 中的选择定义了相应的变量。在 Makefile 文件中将会包含这个文件。
2. 使用 make dep 命令 建立依赖关系。
3. 使用 make bzImage 命令建立内核。
如设置正确将在 arch/i386/boot/ 目录下生成内核 bzImage 文件
4.make bzImage 的流程简单说明
当我们使用 make 命令时, make 程序将首先找到当前目录下的 Makefile 文件。根据 Makefile 文件的语法进行处理。
在主 Makefile 文件中包含了 arch/i386/Makefile 我们 make 的目标 bzImage 即在该文件中定:
bzImage: vmlinux
@$(MAKEBOOT) bzImage # 此命令将解释为: make -C arch/i386/boot bzImage
现在 make 需要先去建立目标 vmlinux 然后再执行 arch/i386/boot/ 目录下的 make bzImae 。我们现在假设 vmlinux 目标已生成,则 arch/i386/boot 目录下的 make 程序将执行如下操作:
tools/build -b bbootsect bsetup compressed/bvmlinux.out ./ bzImage
即将 vmlinux 用 tools/build 工具压缩成目标文件 bzImage (在此过程中,还会构建 build 程序,将 vmlinux 转换成 bvmlinux.out 等,可参考 tools 和 compressed 目录下的 Makefile 文件)。
生成 vmlinux 目标:
在主目录下 Makefile 文件中 vmlinux 生成规则如下:
vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux # 生成 vmlinux
$(NM) vmlinux |grep ?v /(compiled/)/|/(/.o$$/)/|/( [aUw] /)/|/(/./.ng$$/)/|/(LASH[RL]DI/) | sort > System.map # 此命令根据 vmlinux 生成 System.map 文件
在当前设置下此 ld 连接命令被解释为:
ld -m elf_i386 -T /home/arm/linux/arch/i386/vmlinux.lds -e stext arch/i386/kernel/head.o arch/i386/kernel/init_task.o init/main.o init/version.o --start-group arch/i386/kernel/kernel.o arch/i386/mm/mm.o kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o drivers/char/char.o drivers/block/block.o drivers/misc/misc.o drivers/net/net.o drivers/media/media.o drivers/ide/idedriver.o drivers/video/video.o net/network.o /home/arm/linux/arch/i386/lib/lib.a /home/arm/linux/lib/lib.a /home/arm/linux/arch/i386/lib/lib.a --end-group -o vmlinux
即连接程序 ld 将各个 .o 文件连接成目标文件 vmlinux 。
此命令中用到的各个 .o 文件 make 程序会根据 Makefile 文件的规则去自动生成,下面简单介绍一下由 ipc 目录生成 ipc.o 过程:
其 ipc 目录下 Makefile 文件内容如下:
O_TARGET := ipc.o
obj-y := util.o
obj-$(CONFIG_SYSVIPC) += msg.o sem.o shm.o
include $(TOPDIR)/Rules.make # 包含的 Rules.make 文件中为通用的规则;
如我们在 make menuconfig 时选中了 SYSVIPC 选项,则 .config 文件中将定义变量 CONFIG_SYSVIPC=y; 则 obj - y 就等于 util.o msg.o sem.o shm.o ;根据 Rules.make 将四个 .c 文件编译为 .o 文件。再将四个 .o 文件连接成 ipc.o 文件。在我们的当前设置中没有选择 SYSVIPC; 将只使用 util.o 一个文件生成目标 ipc.o ;而 util.o 由 util.c 生成。
当所有需要的 .o 文件生成以后,由 ld 将其连接生成 vmlinux 文件,再将其压缩成我们所需要的内核文件 bzImage 。 Make 程序就执行完了。