上机实践报告Project2_第1页
上机实践报告Project2_第2页
上机实践报告Project2_第3页
上机实践报告Project2_第4页
上机实践报告Project2_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

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

文档简介

1、第 PAGE 20 页 共 NUMPAGES 20 页第 PAGE 1 页 共 NUMPAGES 1 页操作系统实践报告课程名称:操作系统实践 年级: 12上机实践成绩:指导教师:全红艳姓名:修阳上机实践名称:Pintos Project2学号:10122510325上机实践日期:上机实践编号:No。4组号:上机实践时间:一、目的了解Pintos的现有用户程序处理的功能了解Pintos提供的用户程序处理源代码完善Pintos的用户程序处理的功能二、内容与设计思想1、掌握Pintos的磁盘申请、复制等功能2、明确Pintos的用户程序处理中存在的问题3、具体完成以下功能 (a)进程终止时输出信息

2、(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的用户程序处理中存

3、在的问题当系统需要执行一个文件时,就必须先对执行过程的需要的参数进行传递。比如用哪种模式运行,需要用到的文件名称与路径是什么。用一个数组来进行存储,并且把名字和参数分开处理.传递参数时,把堆栈里的参数地址存放在一个新的数组里,以备后用。然后执行字对齐,分别把参数地址、参数的个数、返回地址压栈.系统调用是由系统提供的一组完成底层操作的函数集合,由用户程序通过中断调用,系统根据中断向量表和中断服务号确定函数调用,调用相应的函数完成相应的服务。 此外还有没有内部同步,并行的访问会互相影响,需要用到同步来保证同一时间只有一个进程能访问文件系统代码。一个文件系统被用了多次后会产生大量外部碎片。当操作系统

4、准备运行某一个程序,而这个程序在磁盘上保存的程序代码被修改,则操作系统在运行是,可能会出现异常结果等问题五、实验总结对于这么大而复杂的工程,着实无从下手,难度太大,需要修改的文档和函数非常多基本都是借鉴参考,还是有大量问题没有解决,自己的代码编写能力必须加强,通过不断学习改进提高动手能力,争取以后自己完成项目项目2文档 10122510325 修阳1 需求分析(Pintos中存在的问题 )使得程序能够通过系统调用来与操作系统交互.当用户程序想要用一些内核的功能时,需要用到系统调用。现在只是实现了输出一段消息并且终止用户程序,需要更改代码来实现系统调用所需要的一切。2改进的思想及流程a) 进程终

5、止消息 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|tis_waited=true)/如果t是空的,或者t是死亡了的,或者t在被它的父线程等待return -1;/和原来一样,返回sema_down (tsema);/改变t的信号量t-is_waited=true;/t正在被它的父线

6、程等待着 return texit_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 (cursema);/修改当前线程的信号量/ Destroy the current proce

7、sss page directory and switch back to the kernelonly page directory。 */ pd = curpagedir; if (pd != NULL) /* Correct ordering here is crucial. We must set curpagedir to NULL before switching page directories, so that a timer interrupt cant switch back to the process page directory. We must activate t

8、he 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) 参数传递= 0)/从参数数组最后一个进行循环if_。esp = if_。esp strlen (argvn) - 1;/栈顶指针向前移动,里留出足够的空间给argvnm

9、emcpy (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(offset0)offset=offset+4;/offset转换成正整数if_。esp = if_。esp offset;/栈顶指针向前移

10、动offset位/将参数传递到寄存器中,因为我们的地址是int类型的,而且地址是向下增长的,所以每次在内存中传地址的时候,我们的esp的指针必须每次向下移动4个字节,将argv中的内容根据argc的大小进行传递/for a null argumentif_。esp = if_。esp 4;/栈顶指针向前移动,留一个位置给空参数/Push the argument address in stack into the stack参数地址入栈n = argc-1;/根据前一个while循环可知,此时n=0。/为了再一次进行压栈操作,所以要再赋一次值.while(n=0)if_.esp = if_.e

11、sp 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_.es

12、p = 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_d

13、ead=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 point

14、er (%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 cha

15、r *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 semaph

16、ore 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

17、 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 userpr

18、og/process.h”include ”userprog/pagedir.h#include stdio。hinclude esp) /指向栈顶的指针exit(-1);/如果不合法则调用exit()函数来退出。int syscall=(int )(fesp);/如果地址合法才进行执行系统调用。if(syscall=SYS_WRITE) /根据用户不同的调用号,进行不同的系统调用。if(addr_is_right(f-esp+4)&addr_is_right(f-esp+8)&addr_is_right(fesp+12) /检查这三个地址空间值是否合法int fd = *(int )(f-e

19、sp+4); const char buffer = (char *)(unsigned int )(f-esp+8);unsigned int size = *(unsigned int*)(fesp+12);feax = 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

20、_is_right(f-esp+4))const char *cmd_line = (char *)(unsigned int*)(fesp+4);feax = exec(cmd_line);elseexit(-1);if(syscall=SYS_WAIT)if(addr_is_right(f-esp+4))int pid = *(int )(f-esp+4);feax = wait(pid);elseexit(1);if(syscall=SYS_CREATE)if(addr_is_right(fesp+4)&addr_is_right(f-esp+8))const char *file =

21、(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(fesp+4))const char file = (char )(unsigned int)(f-esp+4);feax = remove(file);elseexit(-1);if(syscall=SYS_OPEN)if(addr_is_right(f-esp+4))const ch

22、ar *file = (char )*(unsigned int*)(f-esp+4);feax = 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(fesp+4)addr_is_right(fesp+8)&addr_is_right(f-esp+12)int fd = (int )(f-esp+4);co

23、nst char *buffer = (char )(unsigned int )(fesp+8);unsigned int size = *(unsigned int)(f-esp+12);feax = read(fd,buffer,size);elseexit(1);if(syscall=SYS_SEEK)if(addr_is_right(f-esp+4)addr_is_right(fesp+8)int fd = *(int )(fesp+4);unsigned int position = (unsigned int )(fesp+8);seek(fd,position);elseexi

24、t(-1);if(syscall=SYS_TELL)if(addr_is_right(fesp+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))/如果

25、当前buffer指向的地址值无效exit(-1);if(fd = 1)putbuf(buffer,size); /写入缓冲中,并返回实际写入的byte数return size;struct thread *t = thread_current();int i = 0;while(ifp; if(fffd = fd)return file_write(f,buffer,size); /最后调用write函数void exit(int status) /终止process,并记录线程的退出状态struct thread *t = thread_current(); /设置指针t指向当前线程texi

26、t_status = status; /设置退出状态int i = 0;while(it-num_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);

27、/通过调用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_creat

28、e来创建一个文件/从一个文件中读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(i t-n

29、um_file_opent-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 *f

30、f = 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

31、thread *t = thread_current();if(f = NULL)return -1;if(t-num_file_openfd = fd; int i = 0;while(i=t-num_file_open) if(topen_filei = 0)t-open_filei = fd; /设置数组中的标志位即第i个文件为fdtnum_file_open+; /设置打开的文件数的值自增break;i+;list_push_back(file_fd_list,ffelem); /将新增记录压入file_fd_list中fd+;if(strcmp(file,t-name) = 0)fi

32、le_deny_write(ff-fp); /文件名和当前线程名不能相等return fffd;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_ne

33、xt (le))/搜索list来找到fd。如果fd不存在list中,则找不到。struct file_fd *ff = list_entry (le, struct file_fd, elem);if(fffd = fd)return file_length(fffp); /调用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;fo

34、r (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 = li

35、st_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(it-num_file_open & t-ope

36、n_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 pointe

37、r,并赋给lestruct file_fd ff = list_entry (le, struct file_fd, elem); /把当前文件信息赋值给ffif(ff-fd = fd) tnum_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中本身就

温馨提示

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

评论

0/150

提交评论