




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精品文档操作系统实践报告课程名称:操作系统实践 年级: 12上机实践成绩:指导教师:全红艳姓名:修阳上机实践名称:Pintos Project2学号:10122510325上机实践日期:上机实践编号:No.4组号:上机实践时间:一、目的1) 了解Pintos的现有用户程序处理的功能2) 了解Pintos提供的用户程序处理源代码3) 完善Pintos的用户程序处理的功能二、内容与设计思想1、掌握Pintos的磁盘申请、复制等功能2、明确Pintos的用户程序处理中存在的问题3、具体完成以下功能 (a)进程终止时输出信息(b) 参数功能(c) 系统调用功能( d) 禁止对可执行文件的写入功能4、撰写实验报告及项目说明三、使用环境Ubuntu 12,Pinos,Geany,C语言四、实验过程与分析、调试过程、创建虚拟磁盘在命令行输入pintos/src/userprog,进行makebuild,然后输入创建磁盘及对其进行分区的指令, 初始化磁盘后复制,将可执行文件elf装入diskpintos-mkdisk filesys.dsk 2 pintos -f qpintos -p ././examples/echo -a echo - -q pintos -q run echo x2.Pintos的用户程序处理中存在的问题当系统需要执行一个文件时,就必须先对执行过程的需要的参数进行传递。比如用哪种模式运行,需要用到的文件名称与路径是什么。用一个数组来进行存储,并且把名字和参数分开处理。传递参数时,把堆栈里的参数地址存放在一个新的数组里,以备后用。然后执行字对齐,分别把参数地址、参数的个数、返回地址压栈。系统调用是由系统提供的一组完成底层操作的函数集合,由用户程序通过中断调用,系统根据中断向量表和中断服务号确定函数调用,调用相应的函数完成相应的服务。 此外还有没有内部同步,并行的访问会互相影响,需要用到同步来保证同一时间只有一个进程能访问文件系统代码。一个文件系统被用了多次后会产生大量外部碎片。当操作系统准备运行某一个程序,而这个程序在磁盘上保存的程序代码被修改,则操作系统在运行是,可能会出现异常结果等问题五、实验总结对于这么大而复杂的工程,着实无从下手,难度太大,需要修改的文档和函数非常多基本都是借鉴参考,还是有大量问题没有解决,自己的代码编写能力必须加强,通过不断学习改进提高动手能力,争取以后自己完成项目 项目2文档 10122510325 修阳1 需求分析(Pintos中存在的问题 )使得程序能够通过系统调用来与操作系统交互。当用户程序想要用一些内核的功能时,需要用到系统调用。现在只是实现了输出一段消息并且终止用户程序,需要更改代码来实现系统调用所需要的一切。2改进的思想及流程a) 进程终止消息 b) 参数传递 c) 系统调用 d) 实现禁止对可执行文件进行读写3.实现方法(代码及说明)a) 进程终止消息intprocess_wait (tid_t child_tid) struct thread *t;t = get_thread (child_tid);/t通过child_tid拿到子线程的所有信息if(t=NULL|t-is_dead=true|t-is_waited=true)/如果t是空的,或者t是死亡了的,或者t在被它的父线程等待return -1;/和原来一样,返回sema_down (&t-sema);/改变t的信号量t-is_waited=true;/t正在被它的父线程等待着 return t-exit_status;/返回当前t的退出状态/*ADD ENDvoidprocess_exit (void) struct thread *cur = thread_current (); uint32_t *pd;/*ADD/* Sema up the parent thread. */printf(%s: exit(%d)n,thread_current()-name,thread_current()-exit_status);/打印当前线程的名字和退出状态sema_up (&cur-sema);/修改当前线程的信号量/* Destroy the current processs page directory and switch back to the kernel-only page directory. */ pd = cur-pagedir; if (pd != NULL) /* Correct ordering here is crucial. We must set cur-pagedir to NULL before switching page directories, so that a timer interrupt cant switch back to the process page directory. We must activate the base page directory before destroying the processs page directory, or our active page directory will be one thats been freed (and cleared). */ cur-pagedir = NULL; pagedir_activate (NULL); pagedir_destroy (pd); b) 参数传递/* A thread function that loads a user process and starts it running. */static voidstart_process (void *file_name_) char *file_name = file_name_; struct intr_frame if_; bool success;/*ADDint n;/后面循环中会用到的,只是一个控制循环的参数。char *token, *save_ptr;/*token指向参数*save_ptr指向指针char *argv50, *arg_addr_in_stack50;/分别定义了两个最大是50的数组,也就是说参数的个数最多是50个int argc = 0;/参数个数/Split up the filename分解文件名for (token = strtok_r (file_name_, , &save_ptr); token != NULL;token = strtok_r(NULL, , &save_ptr)/strtok_r()字符串解析,一直解析到token = NULL即最后一个argvargc = token;/把解析出来的token赋给argv argc+;/*ADD END /* Initialize interrupt frame and load executable. */ memset (&if_, 0, sizeof if_); if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.cs = SEL_UCSEG; if_.eflags = FLAG_IF | FLAG_MBS; success = load (argv0, &if_.eip, &if_.esp);/*ADD/pass argument参数传递/If load successed如果存储成功了的话if (success)/ Push argument into stack把参数压入堆栈n = argc-1;/因为前面的for循环中在退出循环之前又执行了一次argc+/减1表示argv的有效长度while(n= 0)/从参数数组最后一个进行循环if_.esp = if_.esp - strlen (argvn) - 1;/栈顶指针向前移动,里留出足够的空间给argvnmemcpy (if_.esp, argvn, strlen (argvn);/memcpy()字符串的拷贝。/把argvn的值拷贝到if_.esp里,长度是strlen (argvn)arg_addr_in_stackn = (char *)if_.esp;/把堆栈的位置赋值给参数地址n-;/Word align字对齐,四位一对齐int offset = (int)if_.esp % 4;/先算出要多少个offsetif (offset != 0)if(offset=0)if_.esp = if_.esp - 4;/栈顶指针向前移动四位*(void *)if_.esp = (char *)arg_addr_in_stackn;/arg_addr_in_stackn = (char *)if_.esp;/把之前赋给参数地址数组的值赋给现在的栈顶指针/注意类型的不同n-;/由后向前寻找参数地址if_.esp = if_.esp - 4;/栈顶指针向前移动出一个空位*(void *)if_.esp = (char *) if_.esp + 1;/然后+1赋给*(void *)if_.esp/ Push the number of the arguments into stack把参数个数压栈if_.esp = if_.esp - 4;/栈顶指针向前移动出一个空位*(int *)if_.esp = argc;/把个数赋给*(int *)if_.esp/ Push return address into stack.返回地址入栈if_.esp = if_.esp - 4;/栈顶指针向前移动出一个空位*(void *)if_.esp = if_.esp;/当前的返回地址赋给*(void *)if_.esp /*ADD END /* If load failed, quit. */ palloc_free_page (file_name); if (!success) thread_current()-is_dead=true;thread_current()-exit_status=-1; thread_exit (); /* Start the user process by simulating a return from an interrupt, implemented by intr_exit (in threads/intr-stubs.S). Because intr_exit takes all of its arguments on the stack in the form of a struct intr_frame, we just point the stack pointer (%esp) to our stack frame and jump to it. */ asm volatile (movl %0, %esp; jmp intr_exit : : g (&if_) : memory); NOT_REACHED (); c) 系统调用int write(int fd,const char *buffer,unsigned int size);void exit(int status);void halt();int exec(const char *cmd_line);int wait(int pid);bool create(const char *file,unsigned int initial_size);int open(const char *file);int read(int fd,void *buffer,unsigned int size);int filesize(int fd);bool remove(const char *file);void seek(int fd,unsigned int position);unsigned int tell(int fd);void close(int fd);添加的数据结构(共8个): int exit_status /用于记录线程的退出状态struct semaphore sema /线程的信号量int num_file_open/记录正在运行中的线程的数量int open_file128/用于记录线程所开启的文件的编号,这里因为是FAQ /假定一个线程最多可以开启128个文件tid_t parent_tid/用于记录当前线程的父线程的tidbool is_waited /用一个布尔量记录当前线程是否正在被他的父线程等待中bool is_dead /用于判别当前线程是否被杀死(been killed) 该函数实现通过线程的tid可返回该线程: struct thread *get_thread (tid_t tid) 该函数用于检查The function to to check whether the pointer is all right:bool addr_is_right(void *addr)/用于检查该指针指向的地址是否合法struct file_fd /实现了文件的fd可以成功映射到该文件int fd; /记录file的fd的值struct file *fp; /记录指向文件的指针struct list_elem elem; /用于list; 用一个list来存储file_fd:struct list file_fd_list以下是详细代码及分析:#include userprog/syscall.h#include userprog/process.h#include userprog/pagedir.h#include #include #include threads/interrupt.h#include threads/thread.h#include threads/init.h#include threads/vaddr.h#include lib/kernel/stdio.h#include filesys/filesys.h#include filesys/file.h#include devices/input.hstatic void syscall_handler (struct intr_frame *);/用于控制整个系统调用过程struct file_fd /实现了文件的fd可以成功映射到该文件int fd; /记录file的fd的值struct file *fp; /记录指向文件的指针struct list_elem elem; /用于list;struct list file_fd_list; /用来存储file_fdint write(int fd,const char *buffer,unsigned int size);/向一个文件中写入void exit(int status);/终止当前processvoid halt();/停止当前操作系统运行int exec(const char *cmd_line);/开始另一个processint wait(int pid);/等待一个子进程的死亡bool create(const char *file,unsigned int initial_size);/创建一个fileint open(const char *file);/打开一个文件int read(int fd,void *buffer,unsigned int size);/从一个文件中读int filesize(int fd);/获取一个文件的大小bool remove(const char *file);/删除一个文件void seek(int fd,unsigned int position);/改变在文件中的位置unsigned int tell(int fd);/报告在文件中的当前位置void close(int fd);/关闭文件bool addr_is_right(void *addr);/检查地址是否合法/系统调用初始化voidsyscall_init (void) intr_register_int (0x30, 3, INTR_ON, syscall_handler, syscall); list_init (&file_fd_list);/该函数查看当前是哪一个syscall,然后调用相应的系统调用函数static voidsyscall_handler (struct intr_frame *f UNUSED) /读取出中断帧 /系统调用可能会从用户内存中读取或写入函数,/所以在每调用一个函数之前都要先检验堆栈顶指针指向的/地址值是否合法。if(!addr_is_right(f-esp) /指向栈顶的指针exit(-1);/如果不合法则调用exit()函数来退出。int syscall=*(int *)(f-esp);/如果地址合法才进行执行系统调用。if(syscall=SYS_WRITE) /根据用户不同的调用号,进行不同的系统调用。if(addr_is_right(f-esp+4)&addr_is_right(f-esp+8)&addr_is_right(f-esp+12) /检查这三个地址空间值是否合法int fd = *(int *)(f-esp+4); const char *buffer = (char *)*(unsigned int *)(f-esp+8);unsigned int size = *(unsigned int*)(f-esp+12);f-eax = write(fd,buffer,size);elseexit(-1);if(syscall=SYS_EXIT)if(addr_is_right(f-esp+4)int status = *(int *)(f-esp+4);exit(status);elseexit(-1);if(syscall=SYS_HALT)halt();if(syscall=SYS_EXEC)if(addr_is_right(f-esp+4)const char *cmd_line = (char *)*(unsigned int*)(f-esp+4);f-eax = exec(cmd_line);elseexit(-1);if(syscall=SYS_WAIT)if(addr_is_right(f-esp+4)int pid = *(int *)(f-esp+4);f-eax = wait(pid);elseexit(-1);if(syscall=SYS_CREATE)if(addr_is_right(f-esp+4)&addr_is_right(f-esp+8)const char *file = (char *)*(unsigned int*)(f-esp+4);unsigned int size = *(unsigned int*)(f-esp+8);f-eax = create(file,size);elseexit(-1);if(syscall=SYS_REMOVE)if(addr_is_right(f-esp+4)const char *file = (char *)*(unsigned int*)(f-esp+4);f-eax = remove(file);elseexit(-1);if(syscall=SYS_OPEN)if(addr_is_right(f-esp+4)const char *file = (char *)*(unsigned int*)(f-esp+4);f-eax = open(file);elseexit(-1);if(syscall=SYS_FILESIZE)if(addr_is_right(f-esp+4)int fd = *(int *)(f-esp+4);f-eax = filesize(fd);elseexit(-1);if(syscall=SYS_READ)if(addr_is_right(f-esp+4)&addr_is_right(f-esp+8)&addr_is_right(f-esp+12)int fd = *(int *)(f-esp+4);const char *buffer = (char *)*(unsigned int *)(f-esp+8);unsigned int size = *(unsigned int*)(f-esp+12);f-eax = read(fd,buffer,size);elseexit(-1);if(syscall=SYS_SEEK)if(addr_is_right(f-esp+4)&addr_is_right(f-esp+8)int fd = *(int *)(f-esp+4);unsigned int position = *(unsigned int *)(f-esp+8);seek(fd,position);elseexit(-1);if(syscall=SYS_TELL)if(addr_is_right(f-esp+4)int fd = *(int *)(f-esp+4);f-eax = tell(fd);elseexit(-1);if(syscall=SYS_CLOSE)if(addr_is_right(f-esp+4)int fd = *(int *)(f-esp+4);close(fd);elseexit(-1);/实现向一个文件写入int write(int fd,const char *buffer,unsigned int size)if(!addr_is_right(void *)buffer)/如果当前buffer指向的地址值无效exit(-1);if(fd = 1)putbuf(buffer,size); /写入缓冲中,并返回实际写入的byte数return size;struct thread *t = thread_current();int i = 0;while(inum_file_open&t-open_filei!=fd) /搜索open_file arrayi+;if(i=t-num_file_open) /如果当前线程没有打开这个文件,返回-1return -1;if(!list_empty(&file_fd_list) /如果打开了这个文件,搜索file_td_list找到fd对应的file_pointer struct list_elem *le;for (le = list_begin (&file_fd_list);le != list_end (&file_fd_list);le = list_next (le)struct file_fd *ff = list_entry (le, struct file_fd, elem);struct file *f = ff-fp; if(ff-fd = fd)return file_write(f,buffer,size); /最后调用write函数 void exit(int status) /终止process,并记录线程的退出状态struct thread *t = thread_current(); /设置指针t指向当前线程t-exit_status = status; /设置退出状态int i = 0;while(inum_file_open) /关闭所有打开的文件close(t-open_filei);i+;thread_exit(); /调用该函数退出线程void halt()power_off(); /通过调用power_off来终止pintos./执行另一个进程int exec(const char *cmd_line)if(!addr_is_right(void *)cmd_line) /同样对指针指向的地址的合法性进行检查exit(-1);return process_execute(cmd_line); /通过调用process_execute()int wait(int pid)/struct thread *t = get_thread(pid);/sema_down(&t-sema);return process_wait(pid);/创建一个filebool create(const char *file,unsigned int initial_size) /需要的参数是文件名以及文件的大小if(!addr_is_right(void *)file)exit(-1);return filesys_create(file,initial_size); /通过调用filesys_create来创建一个文件/从一个文件中读int read(int fd,void *buffer,unsigned int size)/传入一个缓冲if(!addr_is_right(void *)buffer)exit(-1);if(fd = 0)/如果fd为0,用input_getc从键盘读入,然后return读到的大小int m = 0;for(m = 0 ; m size ; m+)*(char *)buffer = input_getc();buffer+;return size;struct thread *t = thread_current();int i = 0;while(inum_file_open&t-open_filei!= fd)i+; /搜索到文件fdif(i=t-num_file_open) /如果最后t的值与所有当前打开的文件数的值相等,则没有成功搜索到fd文件return -1;if(!list_empty(&file_fd_list) struct list_elem *le;for (le = list_begin (&file_fd_list); le != list_end (&file_fd_list);le = list_next (le) /在file_fd_list中找到fd对应的file_pointerstruct file_fd *ff = list_entry (le, struct file_fd, elem);if(ff-fd = fd)return file_read(ff-fp,buffer,size); /最后调用file_read函数实现读/打开一个文件int open(const char *file)static int fd = 10; /使用一个全局变量确保每一个文件的fd不同if(!addr_is_right(void *)file)exit(-1);struct file *f = filesys_open(file); /打开文件,如果有错返回-1,没有错将返回文件的fd,以及文件的指针struct thread *t = thread_current();if(f = NULL)return -1;if(t-num_file_openfp = f; ff-fd = fd; int i = 0;while(inum_file_open) if(t-open_filei = 0)t-open_filei = fd; /设置数组中的标志位即第i个文件为fdt-num_file_open+; /设置打开的文件数的值自增break;i+;list_push_back(&file_fd_list,&ff-elem); /将新增记录压入file_fd_list中fd+;if(strcmp(file,t-name) = 0)file_deny_write(ff-fp); /文件名和当前线程名不能相等return ff-fd;bool remove(const char *file)if(!addr_is_right(void *)file)exit(-1);return filesys_remove(file);/返回文件大小int filesize(int fd)if(!list_empty(&file_fd_list) struct list_elem *le;for (le = list_begin (&file_fd_list); le != list_end (&file_fd_list);le = list_next (le)/搜索list来找到fd。如果fd不存在list中,则找不到。struct file_fd *ff = list_entry (le, struct file_fd, elem);if(ff-fd = fd)return file_length(ff-fp); /调用file_length返回文件大小 return -1;/搜索list来寻找fd,如果fd对应文件处于open状态,则设置positionvoid seek(int fd,unsigned int position)if(!list_empty(&file_fd_list) struct list_elem *le;for (le = list_begin (&file_fd_list); le != list_end (&file_fd_list);le = list_next (le)struct file_fd *ff = list_entry (le, struct file_fd, elem);if(ff-fd = fd)file_seek(ff-fp,position); /调用file_seek函数实现return ; unsigned int tell(int fd)if(!list_empty(&file_fd_list) struct list_elem *le;for (le = list_begin (&file_fd_list); le != list_end (&file_fd_list);le = list_next (le)struct file_fd *ff = list_entry (le, struct file_fd, elem);if(ff-fd = fd)return file_tell(ff-fp); /调用file_tellreturn -1; void close(int fd)struct thread *t = thread_current(); /指针t指向当前线程int i = 0;while(inum_file_open & t-open_filei!=fd)i+; /当i小于当前线程打开的文件数且i对应的文件不是当前要关闭的文件时,i自增。if(i = t-num_file_open)return; /如果i已经遍历了所有线程当前打开的文件,说明fd对应的文件已经处于close状态。if(!list_empty(&file_fd_list) struct list_elem *le;for (le = list_begin (&file_fd_list); le != list_end (&file_fd_list);le = list_next (le)/在file_fd_list中查找到指向fd的file pointer,并赋给lestruct file_fd *ff = list_entry (le, struct file_fd, elem); /把当前文件信息赋值给ffif(ff-fd = fd) t-num_file_open-; /修改num_file_open的值,表示有一个文件已关闭t-open_filei = 0; /i是当前文件在堆栈中的一个编号,0表示其已关闭file_close(ff-fp); /调用file_close实现文件的关闭list_remove(le);/将le从file_fd_list中删除return;/用于检查当前指针指向的地址值是否合法,合法则返回ture.bool addr_is_right(void *addr)if(addr = NULL) /若地址为空,返回false。return false;else if(!is_user_vaddr(addr) /借用系统中的函数is_user_vaddr进行检查是不是进程的地址空间return false;else if(pagedir_get_page (thread_current()-pagedir,addr) = NULL)return false;elsereturn true;b)实现禁止对可执行文件进行读写pintos中本身就能够实现禁止对可执行文件进行读写。/* Reads SIZE bytes from FILE into BUFFER, starting at offset
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 监理工程师月度考核评分
- 国际结算考试题及答案
- 防煤气中毒安全教育幼儿园
- 生料辊压机培训
- 支原体肺炎健康宣讲
- 2025年中国幕布行业市场全景分析及前景机遇研判报告
- 工地文明施工培训
- 职场文化培训
- 教师家庭教育培训心得
- 护理带教老师教学小讲课
- 公路工程施工组织设计-技术标
- 公司安全员培训课件
- 2023年黄石市黄石港区社区工作者招聘考试真题
- 国家开放大学化工节能课程-复习资料期末复习题
- 汽车行业焊接车间工位缩写
- DB61-T 5068-2023 钢桥面改性聚氨酯混凝土铺装应用技术规程
- 基于水凝胶模板原位合成磷酸钙类骨组织修复材料及表征
- 畜牧兽医毕业论文名字
- 中国联通5G毫米波技术白皮书
- 医疗人文关怀
- 系统规划与管理师-辅助记忆口诀
评论
0/150
提交评论