java操作系统实习报告.docx
- 文档编号:6230274
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:36
- 大小:344.07KB
java操作系统实习报告.docx
《java操作系统实习报告.docx》由会员分享,可在线阅读,更多相关《java操作系统实习报告.docx(36页珍藏版)》请在冰豆网上搜索。
java操作系统实习报告
操作系统实习报告
课程名称:
操作系统实习
专业:
信息科学与工程学院
班级:
计算机本科08—3班
姓名:
赵子斌
学号:
1080417311
指导老师:
董明刚
第一部分操作系统上机指导
一、常用命令练习:
1.使用ls查看当前目录内容;
2.使用ls–all查看当前目录内容
3.使用cd改变当前目录:
4.pwd显示当前路径
5.建立目录:
mkdir目录名
6.删除目录:
rmdir
7.复制文件cp
8.移动文件或目录
9.删除文件
10.显示文件内容:
more(分页显示)
11.显示文件:
cat文件名
二、使用编辑器vi编辑文件
1.首先vi命令是打开vi编辑器
2.最基本的命令I:
当进入刚打开的文件时,不能写入信息,这时按一下键盘上的I键(insert),插入的意思,就可以进入编辑模式了。
如下图所示:
3.当文件编辑完后,需要保存退出,这时需要经过以下几个步骤:
1)按一下键盘上的Esc键;2)键入冒号(:
),紧跟在冒号后面是wq(意思是保存并退出)。
如果不想保存退出,则在第二步键入冒号之后,键入!
q。
如下图所示:
三、添加新用户、修改文件属性
1.添加新用户(在root下,按默认值回答)
2.修改用户口令passwd
3.控制文件属性
4.改变用户的所有权:
chown用户名文件名
5.查看相关命令的帮助:
man命令名
6.显示当前系统中已注册的用户信息:
who
7.显示当前注册的用户信息:
whoami
第二部分操作系统源代码分析
阅读fork.c源文件,分析进程的创建过程
fork.c文件分析:
linux/kernel/fork.c程序
1/*
2*linux/kernel/fork.c
3*
4*(C)1991LinusTorvalds
5*/
6
7/*
8*'fork.c'containsthehelp-routinesforthe'fork'systemcall
9*(seealsosystem_call.s),andsomemiscfunctions('verify_area').
10*Forkisrathersimple,onceyougetthehangofit,butthememory
11*managementcanbeabitch.See'mm/mm.c':
'copy_page_tables()'
12*/
/*
*'fork.c'中含有系统调用'fork'的辅助子程序(参见system_call.s),以及一些其它函数
*('verify_area')。
一旦你了解了fork,就会发现它是非常简单的,但内存管理却有些难度。
*参见'mm/mm.c'中的'copy_page_tables()'。
*/
13#include
包含系统中各种出错号。
(Linus从minix中引进的)。
14
15#include
//还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。
16#include
含有一些内核常用函数的原形定义。
17#include
定义了有关段寄存器操作的嵌入式汇编函数。
18#include
定义了设置或修改描述符/中断门等的嵌入式汇编宏。
19
5.10fork.c程序
-128-
20externvoidwrite_verify(unsignedlongaddress);
21
22longlast_pid=0;
23
////进程空间区域写前验证函数。
//对当前进程的地址addr到addr+size这一段进程空间以页为单位执行写操作前的检测操作。
//若页面是只读的,则执行共享检验和复制页面操作(写时复制)。
24voidverify_area(void*addr,intsize)
25{
26unsignedlongstart;
27
28start=(unsignedlong)addr;
//将起始地址start调整为其所在页的左边界开始位置,同时相应地调整验证区域大小。
//此时start是当前进程空间中的线性地址。
29size+=start&0xfff;
30start&=0xfffff000;
31start+=get_base(current->ldt[2]);//此时start变成系统整个线性空间中的地址位置。
32while(size>0){
33size-=4096;
//写页面验证。
若页面不可写,则复制页面。
(mm/memory.c,261行)
34write_verify(start);
35start+=4096;
36}
37}
38
//设置新任务的代码和数据段基址、限长并复制页表。
//nr为新任务号;p是新任务数据结构的指针。
39intcopy_mem(intnr,structtask_struct*p)
40{
41unsignedlongold_data_base,new_data_base,data_limit;
42unsignedlongold_code_base,new_code_base,code_limit;
43
44code_limit=get_limit(0x0f);//取局部描述符表中代码段描述符项中段限长。
45data_limit=get_limit(0x17);//取局部描述符表中数据段描述符项中段限长。
46old_code_base=get_base(current->ldt[1]);//取原代码段基址。
47old_data_base=get_base(current->ldt[2]);//取原数据段基址。
48if(old_data_base!
=old_code_base)//0.11版不支持代码和数据段分立的情况。
49panic("Wedon'tsupportseparateI&D");
50if(data_limit 51panic("Baddata_limit"); 52new_data_base=new_code_base=nr*0x4000000;//新基址=任务号*64Mb(任务大小)。 53p->start_code=new_code_base; 54set_base(p->ldt[1],new_code_base);//设置代码段描述符中基址域。 55set_base(p->ldt[2],new_data_base);//设置数据段描述符中基址域。 56if(copy_page_tables(old_data_base,new_data_base,data_limit)){//复制代码和数据段。 57free_page_tables(new_data_base,data_limit);//如果出错则释放申请的内存。 58return-ENOMEM; 59} 60return0; 61} 62 63/* 64*Ok,thisisthemainfork-routine.Itcopiesthesystemprocess 5.10fork.c程序 -129- 65*information(task[nr])andsetsupthenecessaryregisters.It 66*alsocopiesthedatasegmentinit'sentirety. 67*/ /* *OK,下面是主要的fork子程序。 它复制系统进程信息(task[n])并且设置必要的寄存器。 *它还整个地复制数据段。 */ //复制进程。 68intcopy_process(intnr,longebp,longedi,longesi,longgs,longnone, 69longebx,longecx,longedx, 70longfs,longes,longds, 71longeip,longcs,longeflags,longesp,longss) 72{ 73structtask_struct*p; 74inti; 75structfile*f; 76 77p=(structtask_struct*)get_free_page();//为新任务数据结构分配内存。 78if(! p)//如果内存分配出错,则返回出错码并退出。 79return-EAGAIN; 80task[nr]=p;//将新任务结构指针放入任务数组中。 //其中nr为任务号,由前面find_empty_process()返回。 81*p=*current;/*NOTE! thisdoesn'tcopythesupervisorstack*/ /*注意! 这样做不会复制超级用户的堆栈*/(只复制当前进程内容)。 82p->state=TASK_UNINTERRUPTIBLE;//将新进程的状态先置为不可中断等待状态。 83p->pid=last_pid;//新进程号。 由前面调用find_empty_process()得到。 84p->father=current->pid;//设置父进程号。 85p->counter=p->priority; 86p->signal=0;//信号位图置0。 87p->alarm=0; 88p->leader=0;/*processleadershipdoesn'tinherit*/ /*进程的领导权是不能继承的*/ 89p->utime=p->stime=0;//初始化用户态时间和核心态时间。 90p->cutime=p->cstime=0;//初始化子进程用户态和核心态时间。 91p->start_time=jiffies;//当前滴答数时间。 //以下设置任务状态段TSS所需的数据(参见列表后说明)。 92p->tss.back_link=0; 93p->tss.esp0=PAGE_SIZE+(long)p;//堆栈指针(由于是给任务结构p分配了1页 //新内存,所以此时esp0正好指向该页顶端)。 94p->tss.ss0=0x10;//堆栈段选择符(内核数据段)[? ? ]。 95p->tss.eip=eip;//指令代码指针。 96p->tss.eflags=eflags;//标志寄存器。 97p->tss.eax=0; 98p->tss.ecx=ecx; 99p->tss.edx=edx; 100p->tss.ebx=ebx; 101p->tss.esp=esp; 102p->tss.ebp=ebp; 103p->tss.esi=esi; 104p->tss.edi=edi; 105p->tss.es=es&0xffff;//段寄存器仅16位有效。 106p->tss.cs=cs&0xffff; 107p->tss.ss=ss&0xffff; 5.10fork.c程序 -130- 108p->tss.ds=ds&0xffff; 109p->tss.fs=fs&0xffff; 110p->tss.gs=gs&0xffff; 111p->tss.ldt=_LDT(nr);//该新任务nr的局部描述符表选择符(LDT的描述符在GDT中)。 112p->tss.trace_bitmap=0x80000000;(高16位有效)。 //如果当前任务使用了协处理器,就保存其上下文。 113if(last_task_used_math==current) 114__asm__("clts;fnsave%0": : "m"(p->tss.i387)); //设置新任务的代码和数据段基址、限长并复制页表。 如果出错(返回值不是0),则复位任务数组中 //相应项并释放为该新任务分配的内存页。 115if(copy_mem(nr,p)){//返回不为0表示出错。 116task[nr]=NULL; 117free_page((long)p); 118return-EAGAIN; 119} //如果父进程中有文件是打开的,则将对应文件的打开次数增1。 120for(i=0;i 121if(f=p->filp[i]) 122f->f_count++; //将当前进程(父进程)的pwd,root和executable引用次数均增1。 123if(current->pwd) 124current->pwd->i_count++; 125if(current->root) 126current->root->i_count++; 127if(current->executable) 128current->executable->i_count++; //在GDT中设置新任务的TSS和LDT描述符项,数据从task结构中取。 //在任务切换时,任务寄存器tr由CPU自动加载。 129set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); 130set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); 131p->state=TASK_RUNNING;/*dothislast,justincase*/ /*最后再将新任务设置成可运行状态,以防万一*/ 132returnlast_pid;//返回新进程号(与任务号是不同的)。 133} 134 //为新进程取得不重复的进程号last_pid,并返回在任务数组中的任务号(数组index)。 135intfind_empty_process(void) 136{ 137inti; 138 139repeat: 140if((++last_pid)<0)last_pid=1; 141for(i=0;i 142if(task[i]&&task[i]->pid==last_pid)gotorepeat; 143for(i=1;i 144if(! task[i]) 145returni; 146return-EAGAIN; 147} 148 进程的创建过程: 程序调用fork创建一个进程,称为子进程。 调用的进程称为父进程。 子进程继承了父进程的几乎所有的属性,当然也具有跟父进程不同的属性。 调用fork会返回两次。 返回值==0,代表子进程;返回值>0,代表父进程。 返回值<0,代表error。 fork正确返回后,在父、子进程中可以直接写代码或者用execl系列函数执行应用程序。 如果是用execl函数执行应用程序,且调用execl成功,那么进程会一直阻塞在execl处,执行完后直接退出进程,而不会再执行execl以后的代码。 用例子完成两个程序child和father之间的数据传递工作: 一、编制并发程序pipeline.c。 在文本编辑中键入程序并保存为pipeline.c。 在该程序中定义管道和文件描述符,并且创建子进程child。 该程序用到的系统调用有pipe()、dup()、fork()、close、execl()、exit,它们的功能分别是建立管道、复制旧的文件描述符到新的文件描述符、创建进程并使子进程与父进程有相同的程序正文、关闭文件描述符、用指定文件覆盖调用程序、撤销当前进程。 阅读程序。 各种系统调用的使用方法都可以通过man命令得到使用帮助。 pipeline.c//定义管道程序 #defineSTD_INPUT0//定义标准输入设备描述符(指针),是linux默认的 #defineSTD_OUTPUT1//定义标准输出设备描述符(指针),是linux默认的 intfd[2];//定义2个文件描述符指针 main() { staticcharprocess1[]="father",process2[]="child"; pipe(fd);//定义管道,返回的fd[0]用于文件读,fd[1]用于文件写 pipeline(process1,process2);//调用自定义函数pipeline() exit (1);//程序结束 } pipeline(char*process1,char*process2) { inti;//用于创建进程的PID while((i=fork())==-1);//创建进程,直到创建成功为止 if(i)//父进程返回时的执行代码 { close(fd[0]);//关闭管道输入描述符(父进程不使用fd[0]) close(STD_OUTPUT);//关闭标准输出描述符1 dup(fd[1]);//指定标准输出描述符1为管道写指针,以后写到标准 输出的内容都写到fd[1]指出的文件 //dup使用最小号码的没有使用的描述符(指针)作为新描述符(指针) close(fd[1]);//关闭原始管道写指针 execl(process1,process1,0);//用程序father覆盖当前程序 printf("fatherfailed.\n");//execl()执行失败 } else//子进程返回时的执行代码 { close(fd[1]);//关闭管道输出描述符(子进程不使用fd[1]) close(STD_INPUT);//关闭标准输入描述符0 dup(fd[0]);//指定标准输入描述符0为管道读指针 close(fd[0]);//关闭原始管道读指针 execl(process2,process2,0);//用程序child覆盖当前程序 printf("childfailed.\n");//execl()执行失败 } exit (2);//程序结束 } 二、编制“管道写”程序father.c作为父进程的一部分工作。 其内容如下: 在文本编辑中键入程序并保存为father.c。 father.c main() { staticcharstring[]=“Parentisusingpipewrite.”; intlen; len=sizeof(string); write(l,string,len);/*将string中的内容写入管道中*/ printf(“parent,parent,parent\n\n\n”); exit(0); } 三、编制“管道读”程序child.c作为子进程的一部分工作。 其内容如下: 在文本编辑中键入程序并保存为child.c。 child.c main() { charoutput[30]; read(0,output,30);/*从管道中读数据并存入output中*/ printf(“%s\nchild,child.\n”,output); return(0); } 四、编译。 gcc为c语言编译器。 gcc-ochildchild.c gcc-ofatherfather.c gcc-opipelinepipeline.c 若编译不成功,则应该用文本编辑器对源程序进行修改调试。 五、运行。 ./pipeline其中,“./”表示当前目录。 若运行不成功,则应该用文本编辑器对源程序进行修改调试。 结果: Parentisusingpipewrite. child,child. 第三部分操作系统原理演示系统的开发 磁盘调度管理的实现 一、设计目的: 加深对操作系统原理的进一步认识,加强实践动手能力和程序开发能力的培养,提高分析问题解决问题的能力,培养合作精神,以巩固和加深磁盘调度的概念。 这次课程设计,就是通过模拟磁盘调度来加深对操作系统中磁盘调度概念的理解及其算法的特点。 二、设计内容: 1.用户可以为程序指定初始需要访问序列; 2.实现最短寻道和电梯调度两种调度算法; 3.根据用户的选择输出实际的访问序列; 三、开发环境: Javajdk1.6环境,BlueJ开发工具 四、分析设计: <一>实验原理: 1.1最短寻道时间优先(SSTF): 该算法选择这样的进程: 要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短。 1.2扫描(SCAN)算法: 该算法不仅考虑到欲访问的磁道与当前磁道间的距离,更优先考虑的是磁头当前的移动方向。 例如,当磁头正在自里向外移动时,SCAN算法所考虑的下一个访问对象,应是其欲访问的磁道,既在当前磁道之外,又是距离最近的。 这样自里向外的访问,直至再无更外的磁道需要访问时,才将磁道换向自外向里移动。 这时,同样也是每次选择这样的进程来调度,即要访问的当前位置内距离最近者,这样,磁头又逐步地从外向里移动,直至再无更里面的磁道要访问,从而避免了出现“饥饿”现像。 由于在这种算法中磁头移动的规律颇似电梯的运行,因而又常称为电梯调度算法。 <二>程序结构: JFrame类是构成窗体的主类。 SSTF类是用来处理SSTF的类。 SCAN类是用来
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 操作系统 实习 报告