头文件和数据结构
内存管理器有一个主头文件mm.h(15800行),每个文件编译时都包含它,大部分包含在/kernel/kernel.h中的文件也被包含到这里。内存管理器害需要include/fcntl.h和include/unistd.h中的定义。内存管理器自己版本的const.h,type.h,glo.h也包含在里面。
const.h(15900行)定义了内存管理其用的常量,其中有些是特别为16位机器设置的。
type.h目前没有使用,它只是以一个框架的形式存在,使内存管理器和MINIX其他部分有同样的组织。proto.h(16100行)收集了在整个内存管理器内需要的函数原型。
内存管理器的全局变量在glo.h中(16200行)。
进程表的内存管理器部分在另一个文件mproc.h中(16300行)。
文件param.h包含了许多用于请求信息中的系统调用参数的宏和4个用于应答消息中域的宏。
内存管理器版本的table.c(16500行)被编译时,将位于glo.h和mpro.h中看到的各种EXTERN变量和结构保留空间。table.h另一个重要的成分是数组call_vec(16515行)。
主程序
内存管理器是独立于内核和文件系统编译和连接的,所以它有自己的主程序。主程序在内核初始化自己之后被启动,主程序在main.c中(16627行),在通过调用mm_init完成自己的初始化之后,内存管理器进入16636行的循环。过程get_work(16663行)和reply(16676行)分别处理实际的接受和发送。这个文件的最后一个过程使mm_init,它初始化内存管理器。
FORK、EXIT和WAIT的实现
FORK,EXIT和WAIT系统调用是由文件forkexit.c中的do_fork,do_exit,do_wait过程实现的。过程do_fork(16832行)按照如下的步骤执行:
l 检查进程表是否满了
l 试为子进程的数据和堆栈分配内存
l 把父进程的数据和堆栈复制到子进程的内存中
l 找到一个空闲的进程表项并把父进程的表项复制进去
l 在进程表输入子进程的内存映射
l 为子进程选择一个进程号
l 告诉内核和文件系统子进程的情况
l 向内核报告子进程的内存映射
l 向父进程和子进程发送应答信息
EXEC的实现
EXEC被包含在过程do_exec(17140行)中,按照如下步骤执行:
l 检查权限——文件是否可执行
l 读取文件头得到各段长度和总长度
l 从调用者处取参数和环境
l 分配新内存和释放旧内存
l 把堆栈复制到新的内存映象中
l 把数据(可能还后正文)段复制到新的内存映象中
l 检查处理setuid、setgid位
l 设置进程表项
l 告诉内核进程现在试可运行的
BRK的实现
位于break.c中的BRK调用的实现试特别简单的,它首先检查新的大小是否可行,随后更新表格以反映这些变化。顶层的过程是do_brk,但是大部分工作是由adjust(17661行)完成的。最后一个过程size_of()(17736行)以块和字节为单位检查段的长度是否能被地址空间容纳下。
信号处理的实现
与信号处理有关的调用由八个,摘要如下:
这些系统调用和信号自己都是在signal.c中处理的。还有一个系统调用REBOOT,因为它用信号中止所有的进程,所以也是在这个文件中处理的,这个调用只被超级用户执行的专门程序使用。
SIGACTION调用支持sigaction和signal函数,他们使进程能改变自己对信号的相应方式。
ALARM系统调用由do_alarm(18056行)控制。
do_pause处理PAUSE系统调用(18115行)。
其他系统调用的实现
文件getset.c包含了一个过程do_getset(18515行),它执行余下的7各内存管理器调用,如下所示:
GETUID和GETGID调用同时返回真实和有效用户号或组号。
PTRACE系统调用提供的最小的调试支持包含在文件trace.c中。共有11个命令可以作为参数传递给PTRACE系统调用,如图所示:
内存管理器工具
余下的文件中包含了工具例程和表格,文件alloc.c使系统对内存的那些部分在被使用那些部分空闲保持跟踪的地方,它由4个入口:
alloc_mem - 请求一块给定大小的内存
free_men - 归还不再需要的内存
max_hole - 计算最大可用空洞的长度
mem_init - 在内存管理器开始运行时初始化空闲表
下一个文件是utility.c,它包含了在内存管理器不同部分的几个杂过程。
--
原文链接: http://202.113.25.72/OSTEACH/upload/UpInstructionFile20051122153900.doc
|