《minix代码解读》word版.doc_第1页
《minix代码解读》word版.doc_第2页
《minix代码解读》word版.doc_第3页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Minix源码解读报告学号:5100309002姓名:邢佳楠以下是我这学期主要阅读过的minix源码内容,主要从几个比较重点的系统调用的实现入手,阅读的足迹涉及KERNEL、PM、VM、VFS和一点PFS:一、 系统的初始化进程:系统启动后,系统将提示选择多个image中一个进行处理。选择映像后,系统进入pre_init() (kernel/arch/i386/pre_init.c) ,做一些开机准备,之后,完成一些参数的设置,读入相应选择的映像。pre_init() 完成后,进入 mpx.S 中的 kernel_init 下的汇编代码。之后进入main() (kernel/main.c) 函数。在main中:(1) 初始化进程表,标记为空。进程结构 proc 在 kernel/proc.h 中定义。(2) 初始化特权表。亦标记为空。特权表记录了进程对应的能够执行的命令,如能够使用的内存范围,能够使用的 I/O 地址,所使用的信号管理器,能够使用 Kernel_call 的权限等等。关于特权的配置,可以看 include/minix/priv.h 其中的常量(3)初始化boot image所提供的一些默认的进程。按照先后次序一一进行初始化,将他们放进进程表中(复制数据),如果进程是IDLE, CLOCK, SYSTEM,或者根系统进程(即再生服务器),那么他们当前可被调度,否则,初始不应该被调度。对于再生服务器进程,作为系统进程且可以被抢占(这是所有系统服务的共性),另外,设置允许陷入等等。对于其它进程,暂时不允许运行。(4)之后设置堆栈,内存映像,将 proc_ptr 指向当前进程,清除标记,入队,设置为可调度状态,开始调度。(5)初始化中断、System Call数组等等二、 IPC的实现:在上一层,由库函数产生中断进入到kernel 中 (lib/libc/arch/ui386/rts/_ipc.S),具体没看,相关头文件主要是include/minix/ipc.h定义,在这个头文件里定义了 9 种消息类型以及 IPC 函数原型。IPC具体由 do_ipc 函数完成 (kernel/proc.c)。同步的 IPC 由 do_sync_ipc 函数完成,接收的参数有发送者、发送的 flag、接受者、消息内容的指针,异步的IPC由mini_senda 完成(这部分没仔细看)。其中只有RECEIVE 接收 ANY 参数;对于其它如 SEND, SENDREC, NOTIFY 来说,必须指定一个 endpoint 作为对象。使用 isokendpt 检查该 endpoint 是否有效,并将其转换为 process number,如果有效返回 true。检查进程是否有权限执行相应的 call。对于 Kernel Call,只允许 SENDREC。然后执行相应的任务,如 mini_send(), mini_receive(), mini_notify()。mini_send() 首先检查目的进程是否正在处于 block 状态等待这条消息,如果是,则向它复制信息 (caller-p_delivermsg),解锁这个进程;否则,则将发来信息的进程出队,block 它(置 RTS_SENDING 位)同时将这个进程放到目的进程的等待列表中。 mini_receive() 首先检查是否消息队列是否为空且是它想获取的消息,如果是则获取他,解锁caller;否则,再检查是否有异步消息发送(检查 MF_ASYNMSG),否则,block它(置RTS_RECEIVING位)。mini_notify() 首先检查目的进程是否在等待消息,一个进程在执行 SENDREC 系统调用时可同时处于发送和接收状态。如果是则copy该消息,否则,加入到消息位图中(priv结构的s_notify_pending)在block之前要调用deadlock函数检测是否会产生死锁。如果产生死锁,则返回该死锁长度。完成 do_ipc 后,执行 switch_to_user 回到原来部分。三、 Fork()的实现对于系统调用 fork(),用户进程执行 fork() 调用,将会进入到 lib/libc/posix/_fork.c 中定义的 fork(),执行系统调用 _syscall(PM_PROC_NR, FORK, &m),向进程管理器(PM)发送一个消息创建一个新进程,以 sendrec 方式发送。消息传递到 PM 后,PM 执行了 do_fork() 函数 (servers/pm/forkexit.c)。do_fork() 函数检查进程表是否还有空间,接着,查看是否有 mproc 子进程的 slot,如果没有返回错误。接下来,执行 vm_fork(),向 VM 发出消息。转到Servers/vm/fork.c中,VM拷贝一份父进程的 vmproc 信息到子进程的 vmproc 中,分配页表和相应的虚拟地址空间。Minix 默认使用的是独立的 I 和 D 空间,即只需为进程分配其数据段和堆栈段的所需内存,正文段与父进程共享,代码段是不复制的。增加的是全局共享数据和对文件描述符的引用和堆栈。复制内存内容,设置对应的 vm_flags 和 priv 结构体中的 flags,告知 kernel 成功 fork(调用 sys_fork),陷入 Kernel。sys_fork 对应了 kernel/system/do_fork(),首先复制 proc 结构,并使之暂时不能运行,然后去除特权级别,返回。返回后, PM发送异步消息,通知 VFS 进行相应的 fork 操作(servers/vfs/misc.c pm_fork())。如子进程将继承父进程的文件描述符等等。复制 fproc 结构,复制 Root directory 和 Working Directory,返回后,发送一个 SIGSTOP 给子进程。最终返回子进程的 pid。至此,fork 结束。四、 Exec()的实现执行 execvp 后,首先分配空间,获得当前环境变量 $PATH 等,传递适当参数给 execve,并让 execve 最终调用 SYSCALL:_syscall(PM_PROC_NR, EXEC, &m),由 PM 处理系统调用。处理系统调用的函数在 server/pm/exec.c。PM 接收该系统该系统调用后,以 PM_EXEC 的消息类型将请求转发给 VFS。VFS 接收到该消息后,执行 pm_exec。在其中:查看是不是 Super User;通过 fetch_name 函数,从用户空间复制数据(调用 Kernel Call),获得 exec 的文件名;调用 eat_path 打开工作目录或者是根目录。检查文件头是否符合要求,检查文件权限是否可以打开。调用 req_stat 打开文件。调用 read_header 读取文件头结构.读取完成后,分析是否是可执行文件,检查 CPU,检查其 I/D 位。读取文字段、数据段和栈段大小,如果是 I/D 空间非独立的,那么数据段大小应与正文段大小合并。接着执行 exec_newmem 生成一个 exec_newmem 的结构,将结构地址作为消息内容,发送给 PM。PM 接收到后,执行 do_exec_newmem()从 VFS 中复制数据到 PM 本地,再执行 vm_exec_newmem()。vm_exec_newmem 发出 taskcall 到 VM。VM 接收到后,执行 do_exec_newmem(servers/vm/exec.c)。其中计算各段的长度,并检查是否符合要求;调用 new_mem 进行分配新内存和释放旧内存。调用 pt_free 根据原来的页表,对原来的内存进行释放。调用 pt_new 分配新的页表,调用 proc_new 为进程分配内存。复制原来的 vmproc 结构,然后在原来的 slot 上面替换进程。再调用 free_proc 和 clear_proc 清除原来进程的相关内存的信息,比如页表的引用和内存等等。new_mem 完成后,记录下返回的 inode 编号,设备号码和 inode 修改时间。VM 完成工作,回复 PM。此时 PM 接收到回复信息,如果 exec 成功,那么保存 command line、参数等返回,答复 VFS 请求。VFS完成复制等操作后答复 PM。PM 接收到消息后,又执行 exec_restart。看是否执行成功,如果不成功则像它发送 SIGKILL,如果成功,则完善 mproc 结构,初始化信号处理,调用 sys_exec 通知 Kernel exec 完成。Kernel 完成的是复制 command name,设置栈指针和 PC 等,完成后返回 PM。五、 Wait/exit()的实现wait:告知 PM 处于等待某个进程退出的状态,一旦子进程退出或者有父进程不想等待,那么返回。exit: PM接收消息,清除计时器,对父进程计费,发送 SIGHUP 给进程租,告知等待它的进程,同时通知 VFS; VFS 接收到消息后,关闭它打开的文件描述符,清除 fproc 位回复 PM; PM 接收到 VFS 的回复通知 Kernel 完成 exit;Kernel去除中断处理器,释放地址空间,重置 timer,清除 proc 和 priv 结构,答复 PM 已完成; M 接收到 Kernel 的答复,通知 VM,令 VM 清除掉为它非配的内存,以及清除它的 vmproc 结构; VM 答复,PM 清除 mproc 结构,完成六、 Read()的实现:read 库函数被调用后,向 VFS 发出 syscall(READ),VFS 执行 read_write 函数read_write 函数首先验证文件描述符是否有效,并通过文件描述符获取 vnode。如果是 pipe 文件,那么执行 rw_pipe(),如果一个进程从空管道中读,但是写

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论