您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 交通运输 > 西安交通大学操作系统课内实验报告
西安交通大学实验报告——操作系统原理课内实验姓名:班级:学号:实验一用户接口实验一、实验目的1、理解并掌握面向操作命令的接口Shell,学会简单的shell编码。2、理解操作系统调用的运行机制,掌握创建系统调用的方法。二、实验内容1、控制台命令接口实验理解面向操作命令的接口shell和进行简单的shell编程。该实验是通过“几种操作系统的控制台命令”、“终端处理程序”、“命令解释程序”和“Linux操作系统的bash”来让实验者理解面向操作命令的接口shell和进行简单的shell编程。查看bash版本。编写bash脚本,统计/my目录下c语言文件的个数2)系统调用实验。2、系统调用实验理解操作系统调用的运行机制。该实验是通过实验者对“Linux操作系统的系统调用机制”的进一步了解来理解操作系统调用的运行机制;同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。编程调用一个系统调用fork(),观察结果。编程调用创建的系统调用foo(),观察结果。自己创建一个系统调用mycall(),实现功能:显示字符串到屏幕上。编程调用自己创建的系统调用。三、实验准备为了使用户通过操作系统完成各项管理任务,操作系统必须为用户提供各种接口来实现人机交互。经典的操作系统理论将操作系统的接口分为控制台命令和系统调用两种。前者主要提供给计算机的操作人员对计算机进行各种控制;而后者则提供个程序员,使他们可以方便地使用计算机的各种资源。四、实验步骤及结果1、控制台命令接口实验(1)查看bash版本操作:在shell提示符下输入:$echo$BASH_VERSION结果:版本是4.2.42(1)-release(2)建立bash脚本,输出Helloword操作:在编辑器中输入以下内容#!/bin/bashechoHelloWorld!结果:操作:执行脚本使用指令:$./text结果:(3)编写bash脚本:统计/my目录下c语言文件的个数通过bash脚本,可以有多种方式实现这个功能,而使用函数是其中个一个选择。在使用函数之前,必须先定义函数。进入自己的工作目录,编写名为count的文件。脚本程序:#!/bin/bashfunctioncount{echo–nNumberofmatchesfor$1:#接收程序的第一个参数ls$1|wc–l#对子程序的第一个参数所在的目录进行操作}将count文件复制到当前目录下,然后在当前目录下建立文件夹,在my目录下建立几个c文件,以便用来进行测试。2、添加系统调用(1)编程调用一个系统调用fork(),观察结果。源程序:#includestdio.hintmain(){intiUid;iUid=fork();if(iUid==0)for(;;){printf(Thisischildprocess.\n);sleep(1);}if(iUid0)for(;;){printf(Thisisparentprocess.\n);sleep(1);}if(iUid0)printf(Cannotusesystemcall.\n);return0;}实验结果:(2)操作:1.Linux-3.0.tar.bz2拷贝到/usr/src目录下——命令:cplinux-3.0.tar.bz2/usr/src/2.打开终端,获得root权限——命令:sudo–s3.进入/usr/src目录——命令:cd/usr/src4.解压linux源码——命令:tarxvzflinux-3.0.tar.bz25.进入目录linux-3.0.5——命令:cdlinux-3.06.添加系统调用——:geditkernel/myservice.c在文本编辑器中添加#includelinux/kernel.h#includelinux/linkage.hasmlinkagevoidsys_mycall(){printk(KERN_INFOHello,world!\n);return;}7.修改kernel/Makefile添加生成myservice.c添加到Makefile的编译规则中:obj-y+=myservice.o8..修改arch/x86/include/asm/unistd_32.h,添加以下内容:#define__NR_mycallSYS_ID//SYS_ID表示新添加系统调用的调用号并修改文件中的NR_syscalls,将其值增加19..修改arxh/x86/include/asm/syscalls.h添加以下内容:asmlinkagevoidsys_mycall();10.修改arch/x86/kernel/syscall_table_32.S,添加以下内容:.longsys_mycall11.配置内核(仅仅修改localversions即可)——命令:makemenuconfig12.编译内核——命令:make–j4bzImage(开4个线程编译)13.编译内核模块——命令:make–j4modules14.安装内核模块——命令:makemodules_install15.安装内核——命令:makeinstall16.重启系统,在系统选择页面选择进入自己编译的linux-3.0内核17.在桌面建立测试的C程序test.c程序内容如下:#includestdio.hintmain(intargc,char*argv[]){syscall(SYS_ID);//SYS_ID表示新添加系统调用的调用号return0;}18.编译程序——gcctest.c–oa.out19.运行程序——./a.out20.查看内核日志(printk的输出信息在内核日志中):dmesg结果:(1)编译内核成功截图:(2)编译模块成功截图:五、实验问题及分析在进行内核编译时,遇到的困难就是将缺少的程序补入,但因为本省Ubantu所带的编辑器很不好用,在输入过程中就花费了非常大的时间。但最后经过学长的帮助顺利完成。在编译期间有经历了一个多小时的时间,最后编译成功。六、实验心得通过本次实验,我了解并初步掌握了面向操作命令的接口Shell,学会了简单的shell编码,理解了操作系统调用的运行机制,掌握了创建系统调用的方法。本次实验通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这让我们初步了解了操作系统的生成过程。虽然在实验过程中遇到了不少问题,但最终在学长的帮助下,最终还是成功了。最后看见自己的实验结果心里还是挺高兴的。总之,这次实验我们学习了linux系统的使用方法,掌握了一些基本的linux命令,学习了添加系统调用的方法,更深入的了解了操作系统,为我们以后的工作学习打下坚实的基础。实验二:进程管理实验一、实验目的1、理解进程的概念,知道进程与程序的区别;2、理解并发执行、进程互斥及进程通信的基本概念;3、了解并掌握进程管理的机制和操作步骤。二、实验内容1、编制实现软中断通信的程序使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上发出的中断信号(即按delete键),当父进程接收到这两个软中断的某一个后,父进程用系统调用kill()向两个子进程分别发出整数值为16和17软中断信号,子进程获得对应软中断信号,然后分别输出下列信息后终止:Childprocess1iskilledbyparent!!Childprocess2iskilledbyparent!!父进程调用wait()函数等待两个子进程终止后,输入以下信息,结束进程执行:Parentprocessiskilled!!多运行几次编写的程序,简略分析出现不同结果的原因。2、编制实现进程的管道通信的程序使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话:Childprocess1issendingamessage!Childprocess2issendingamessage!而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求:父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。三、实验步骤及结果分析1、进程的软中断通信(1)算法流程图:软中断通信程序流程图(2)程序源代码:#includestdio.h#includesignal.h#includeunistd.h#includesys/types.hintwait_flag;voidstop();main(){intpid1,pid2;//定义两个进程号变量signal(3,stop);//或者signal(14,stop);while((pid1=fork())==-1);//若创建子进程1不成功,则空循环if(pid10){//子进程创建成功,pid1为进程号while((pid2=fork())==-1);//创建子进程2if(pid20){wait_flag=1;sleep(5);//父进程等待5秒kill(pid1,16);//杀死进程1kill(pid2,17);//杀死进程2wait(0);//等待第1个子进程1结束的信号wait(0);//等待第2个子进程2结束的信号printf(\nParentprocessiskilled!!\n);exit(0);//父进程结束}else{wait_flag=1;signal(17,stop);//等待进程2被杀死的中断号17printf(\nChildprocess2iskilledbyparent!!\n);exit(0);}}else{wait_flag=1;signal(16,stop);//等待进程1被杀死的中断号16printf(\nChildprocess1iskilledbyparent!!\n);exit(0);}}voidstop(){wait_flag=0;}(3)实验结果:(4)简要分析1)signal函数上述程序中,调用函数signal()都放在一段程序的前面部位,而不是在其他接收信号处。这是因为signal()的执行起的作用只是为进程指定信号量16和17,以及分配相应的与stop()过程连接的指针。因而signal()函数必须在程序前面部分执行。2)wait函数在父进程中调用第1个wait(0)后,则父进程被阻塞。进入等待第一个子进程运行结束的队列,等待子进程结束。当子进程结束后,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()返回继续执行原程序。同样的方式,父进程继续执行第二个wait(0),并再次阻塞,等待第2个子进程运行结束。当第二个子进程运行结束后父进程继续执行剩余的语句。3)关于exit函数该函数中每个进程退出时都用了语句exit(0),这是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。进程终止时,则由系统内核产生一个代表异常终止原因的终止状态,该进程的父进程都能用wait()得到其终止状态。在子进程调用exit()后,子进程的结束状态会返回给系统内核,由内核根据状态字生成终止状态,供父进程在wait()中读取数据。若子进程结束后,父进程还没有读取子进程的终止状态,则子进程就变成了“孤儿进程”,系统进程init会自动“收养”该子进程,成为该子进程的父进程,即父进程标识号变成1,当子进程结束时,init会自动调用wait()读取子进程的遗留数据,从而避免在系统中留下大量的垃圾。4)结果显示上述结果中“Childprocess1iskilledbyparent!!”和“Childprocess2iskilledbyparent!!”相继出现,当运行几次后,谁在前谁在后是随机的。这是因为:从进程调度的角度看,子进程被创建后处于就绪态。此时,父进程和子进程作为两个独立的进程,共享同一个代码段,分别参加调度、执行,直至进程结束。但是谁会先被调度程序选中执行,则与系统的调
本文标题:西安交通大学操作系统课内实验报告
链接地址:https://www.777doc.com/doc-1850320 .html