linux0.11学习笔记(1)

发布软件包包含内容:

bootimage.Z - 具有美国键盘代码的压缩启动映像文件;

rootimage.Z - 以1200kB 压缩的根文件系统映像文件;
linux-0.11.tar.Z- 内核源代码文件;
as86.tar.Z - linux bruce evans‘二进制执行文件;
是16 位的汇编程序和装入程序;

INSTALL-0.11 - 更新过的安装信息文件。


不足之处:不包括有关进程等待队列、虚拟文件系统、TCP/IP网络等方面的一些当前非常重要的代码。


目录:

Linux/目录下:各个文件夹以及内核代码的总体Makefile文件的内容。

boot/目录下的三个汇编程序,其中包括磁盘引导程序bootsect.s、32 位运行启动代码程序head.s 和获取BIOS 中参数的setup.s 汇编程序。

init/目录中内核系统的初始化程序main.c。它是内核完成所有初始化工作并进入正常运行的关键地方。

kenel/目录中的所有程序

fs/目录中的文件系统程序

mm/目录中的内存管理程序。要透彻地理解这方面的内容,需要对Intel 80X86 微处理器的保护模式运行方式有足够的理解,包含有较为完整的有关80X86 保护模式运行方式的说明,这些知识基本上是从Intel 80386 程序员编程手册(Intel 80386 Programmer‘s ReferenceManual) 中摘录下来的

include/目录中的所有头文件进行详细说明,基本上对每一个定义、每一个常量或数据
结构都进行了详细注释。

lib/目录中的所有文件。由于这个版本较低,所以这里的内容并不是很多,可以很快地看完。

tools/目录下的build.c 程序。这个程序并不会包括在编译生成的内核映像(image)文件中,它仅用于将内核中的磁盘引导程序块与其它主要内核模块连接成一个完整了内核映像(kernelimage)文件。


在Linux 操作系统上,这些程序包括X 窗口系统、shell 命令解释系统以及那些内核编程接口等系统程序


在单内核模式的系统中,操作系统所提供服务的流程为:应用主程序使用指定的参数值执行系统调用指令(int x80),使CPU 从用户态(User Mode)切换到核心态(Kernel Model),然后操作系统根据具体的参数值调用特定的系统调用服务程序,而这些服务程序则根据需要再底层的一些支持函数以完成特定的功能。在完成了应用程序所要求的服务后,操作系统又从核心态切换回用户态,返回到应用程序中继续执行后面的指令。因此概要地讲,单内核模式的内核也可粗略地分为三个层次:调用服务的主程序层、执行系统调用的服务层和支持系统调用的底层函数。


Linux 内核主要由5 个模块构成,它们分别是:进程调度模块、内存管理模块、文件系统模块、进程间通信模块和网络接口模块。


进程调度模块用来负责控制进程对CPU 资源的使用。所采取的调度策略是各进程能够公平合理地访问CPU,同时保证内核能正时地执行硬件操作。内存管理模块用于确保所有进程能够安全地共享机器主内存区,同时,内存管理模块还支持虚拟内存管理方式,使得Linux 支持进程使用比实际内存空间更多大的内存容量。并可以利用文件系统把暂时不用的内存数据块会被交换到外部存储设备上去,当需要时再交换回来。文件系统模块用于支持对外部设备的驱动和存储。虚拟文件系统模块通过向所有的外部存储设备提供一个通用的文件接口,隐藏了各种硬件设备的不同细节。从而提供并支持与其它操作系统兼容的多种文件系统格式。进程间通信模块子系统用于支持多种进程间的信息交换方式。网络接口模块提供对多种网络通信标准的访问并支持许多网络硬件。


linux
├─ boot 系统引导汇编程序
├─ fs 文件系统
├─ include 头文件(*.h)
│ ├─ asm 与CPU 体系结构相关的部分
│ ├─ linux Linux 内核专用部分
│ └─ sys 系统数据结构部分
├─ init 内核初始化程序
├─ kernel 内核进程调度、信号处理、系统调用等程序
│ ├─ blk_drv 块设备驱动程序
│ ├─ chr_drv 字符设备驱动程序
│ └─ math 数学协处理器仿真处理程序
├─ lib 内核库函数
├─ mm 内存管理程序
└─ tools 生成内核Image 文件的工具程序


码目录中含有14 个子目录,总共包括102 个代码文件


bootsect.s 程序是磁盘引导块程序,编译后会驻留在磁盘的第一个扇区中(引导扇区,0 磁道(柱面),0 磁头,第1 个扇区)。在PC 机加电ROM BIOS 自检后,将被BIOS 加载到内存0x7C00 处进行执行。
setup.s 程序主要用于读取机器的硬件配置参数,并把内核模块system 移动到适当的内存位置处。
head.s 程序会被编译连接在system 模块的最前部分,主要进行硬件设备的探测设置和内存管理页面的初始设置工作。


头文件目录中总共有32 个.h 头文件。其中主目录下有13 个,asm 子目录中有4 个,linux 子目录中有10 个,sys 子目录中有5 个


<a.out.h> a.out 头文件,定义了a.out 执行文件格式和一些宏。
<const.h> 常数符号头文件,目前仅定义了i 节点中i_mode 字段的各标志位。
<ctype.h> 字符类型头文件。定义了一些有关字符类型判断和转换的宏。
<errno.h> 错误号头文件。包含系统中各种出错号。(Linus 从minix 中引进的)。
<fcntl.h> 文件控制头文件。用于文件及其描述符的操作控制常数符号的定义。
<signal.h> 信号头文件。定义信号符号常量,信号结构以及信号操作函数原型。
<stdarg.h> 标准参数头文件。以宏的形式定义变量参数列表。主要说明了-个类型(va_list)和
三个宏(va_start, va_arg 和va_end),用于vsprintf、vprintf、vfprintf 函数。
<stddef.h> 标准定义头文件。定义了NULL, offsetof(TYPE, MEMBER)。
<string.h> 字符串头文件。主要定义了一些有关字符串操作的嵌入函数。
<termios.h> 终端输入输出函数头文件。主要定义控制异步通信口的终端接口。
<time.h> 时间类型头文件。其中最主要定义了tm 结构和一些有关时间的函数原形。
<unistd.h> Linux 标准头文件。定义了各种符号常数和类型,并申明了各种函数。如定义了
__LIBRARY__,则还包括系统调用号和内嵌汇编_syscall0()等。
<utime.h> 用户时间头文件。定义了访问和修改时间结构以及utime()原型。


<asm/io.h> io 头文件。以宏的嵌入汇编程序形式定义对io 端口操作的函数。
<asm/memory.h> 内存拷贝头文件。含有memcpy()嵌入式汇编宏函数。
<asm/segment.h> 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。

<asm/system.h> 系统头文件。定义了设置或修改描述符/中断门等的嵌入式汇编宏。


<linux/config.h> 内核配置头文件。定义键盘语言和硬盘类型(HD_TYPE)可选项。
<linux/fdreg.h> 软驱头文件。含有软盘控制器参数的一些定义。
<linux/fs.h> 文件系统头文件。定义文件表结构(file,buffer_head,m_inode 等)。
<linux/hdreg.h> 硬盘参数头文件。定义访问硬盘寄存器端口,状态码,分区表等信息。
<linux/head.h> head 头文件,定义了段描述符的简单结构,和几个选择符常量。
<linux/kernel.h> 内核头文件。含有一些内核常用函数的原形定义。
<linux/mm.h> 内存管理头文件。含有页面大小定义和一些页面释放函数原型。
<linux/sched.h> 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。
<linux/sys.h> 系统调用头文件。含有72 个系统调用C 函数处理程序,以‘sys_‘开头。
<linux/tty.h> tty 头文件,定义了有关tty_io,串行通信方面的参数、常数。


<sys/stat.h> 文件状态头文件。含有文件或文件系统状态结构stat{}和常量。
<sys/times.h> 定义了进程中运行时间结构tms 以及times()函数原型。
<sys/types.h> 类型头文件。定义了基本的系统数据类型。
<sys/utsname.h> 系统名称结构头文件。
<sys/wait.h> 等待调用头文件。定义系统调用wait()核waitpid()及相关常数符号。


件main.c用于执行内核所有的初始化工作,然后移到用户模式创建新进程,并在控制台设备上运行shell 程序。


exit.c 程序主要包括用于处理进程终止的系统调用。包含进程释放、会话(进程组)终止和程序退
出处理函数以及杀死进程、终止进程、挂起进程等系统调用函数。
fork.c 程序给出了sys_fork()系统调用中使用了两个C 语言函数:find_empty_process()和
copy_process()。
mktime.c 程序包含一个内核使用的时间函数mktime(),用于计算从1970 年1 月1 日0 时起到开机
当日的秒数,作为开机秒时间。仅在init/main.c 中被调用一次。
panic.程序包含一个显示内核出错信息并停机的函数panic()。
printk.c 程序包含一个内核专用信息显示函数printk()。
sched.c 程序中包括有关调度的基本函数(sleep_on、wakeup、schedule 等)以及一些简单的系统调
用函数。另外还有几个与定时相关的软盘操作函数。
signal.c 程序中包括了有关信号处理的4 个系统调用以及一个在对应的中断处理程序中处理信号的
函数do_signal()。
sys.c 程序包括很多系统调用函数,其中有些还没有实现。
system_call.s 程序实现了linux 系统调用(int 0x80)的接口处理过程,实际的处理过程则包含
在各系统调用相应的C 语言处理函数中,这些处理函数分布在整个linux 内核代码中。
vsprintf.c 程序实现了现在已经归入标准库函数中的字符串格式化函数。


内核的编译:

1,修改makefile

a. 将gas =>as, gld=>ld。现在gas 和gld 已经直接改名称为as 和ld 了。
b. as(原gas)已经不用-c 选项,所以要将Makefile, 因此需要去掉其-c 编译选项。在内核主目录Linux下makefile 文件中,是在34 行上。
c. 去掉gcc 的编译标志选项:-fcombine-regs、-mstring-insns 以及所有子目录中Makefile 中的这两个选项。在94 年的gcc 手册中就已找不到-fcombine-regs 选项,而-string-insns 是Linus 自己对gcc的修改增加的选项,所以你我的gcc 中肯定不包括这个优化选项。
d. 在gcc 的编译标志选项中,增加-m386 选项。这样在RedHat 9 下编译出的内核映像文件中就不含有80486 及以上CPU 的指令,因此该内核就可以运行在80386 机器上

2,as86 编译程序不能识别c 语言的注释语句,因此需要使用!注释掉boot/bootsect.s 文件中的C 注释语句。

3,原来align 后面带的数值是指对起内存位置的幂次值,而现在则需要直接给出对起的整数地址值。因此,原来的语句:

.align 3
需要修改成(2 的3 次幂值2^3=8):
.align 8

4,由于对as 的不断改进,目前其自动化程度越来越高,因此已经不需要人工指定一个变量需使用的CPU 寄存器。因此内核代码中的__asm__("ax")需要全部去掉。例如s/bitmap.c 文件的第20 行、26 行上,fs/namei.c 文件的第65 行上等。在嵌入汇编代码中,另外还需要去掉所有对寄存器内容无效的声明。例如include/string.h 中第84 行:
:"si","di","ax","cx");

需要修改成:

: );


(32)

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。