您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 交通运输 > 操作系统课内实验报告--西安交通大学
实验报告实验课程:操作系统原理学生姓名:高君宇学号:2110505112专业班级:计算机15班2013年12月29日实验一:用户接口实验一、实验内容1)控制台命令接口实验该实验是通过“几种操作系统的控制台命令”、“终端处理程序”、“命令解释程序”和“Linux操作系统的bash”来让实验者理解面向操作命令的接口shell和进行简单的shell编程。A查看bash版本。A编写bash脚本,统计/my目录下c语言文件的个数2)系统调用实验该实验是通过实验者对“Linux操作系统的系统调用机制”的进一步了解来理解操作系统调用的运行机制;同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。A编程调用一个系统调用fork(),观察结果。A编程调用创建的系统调用foo(),观察结果。A自己创建一个系统调用mycall(),实现功能:显示字符串到屏幕上。A编程调用自己创建的系统调用。二、实验准备为了使用户通过操作系统完成各项管理任务,操作系统必须为用户提供各种接口来实现人机交互。经典的操作系统理论将操作系统的接口分为控制台命令和系统调用两种。前者主要提供给计算机的操作人员对计算机进行各种控制;而后者则提供个程序员,使他们可以方便地使用计算机的各种资源。三、源程序1、控制台命令接口实验(1)查看bash版本在shell提示符下输入:$echo$BASH_VERSION我们的版本是4.2.37(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)系统调用是操作系统为程序员提供的接口服务。使用系统调用,程序员可以更充分的利用计算机资源,使编写的程序更加灵活,功能更加强大。程序员在对系统充分了解的情况下甚至可以订做系统调用,实现那些非专业程序员所难以实现的功能。同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。a.添加源代码在/usr/src/linux/kernel/sys.c文件中添加源代码,如下所示:asmlinkageintsys_foo(intx){printf(“%d\n”,x);}b.连接新的系统调用进入目录/usr/src/linux/include/asm-i386/,打开文件unistd.h。这个文件包含了系统调用的清单,用来给每个系统调用分配一个唯一的号码。进入/usr/src/linux/arche/i386/kernel/,打开文件entry.S。重新编译内核配置内核(建议使用默认配置,仅仅修改localversions即,可当然也可以把一些无用的模块去掉)makemenuconfig编译内核(-jN中的N表示使用多少个线程编译,一般为处理器数目+1)make-j5bzImage编译内核模块make-j5modules安装内核模块(需要root权限)提示:模块被安装在/lib/modules/versions/下(比如2.6.31内核在config时设定其的localversions为-myservice,那么versions为2.6.31-myservice)sudomakemodules_install安装内核提示:在较新的Linux发行版中会自动生成init内存文件系统,并将配置文件、内核及init内存文件系统拷贝到/boot目录下,最后更新引导。重启系统完成以上配置后,重新启动系统进入自己的新系统(2)编程调用一个系统调用fork(),观察结果。#includestdio.hintmain(){intiUid;iUid=fork();if(iUid==0)for(;;){printf(Thisisparent.\n);sleep(1);}if(iUid0)for(;;){printf(Thisischild.\n);sleep(1);}if(iUid0)printf(Cannotusesystemcall.\n);return0;}编程调用创建的系统调用foo(),观察结果。#includestdio.h#includelinux/unistd.h_syscall1(char*,foo,int,ret)main(){intI,J;I=100;J=0;J=foo(I);printf(Thisistheresultofnewkernel\n);printf(%d,j);}编程调用自己创建的系统调用。#includelinux/unistd.hsyscall1(char*,mycall,int,ret)intmain(){char*str;charstring[50];str=string;str=Thisstringwillbedisplayed.;mycall(str);return0;}附:内核编译编译内核的基本步骤(1)将vm和win共享的sharedfolders文件夹中的linux-3.0.5.tar.bz2拷贝到/usr/src目录下更改用户权限sudo–sa.进入sharedfolders:cd/mnt/hfgs/sharedfolders/b.拷贝:cplinux-3.0.5.tar.bz2/usr/src/(2)解压linux源码:进入目录/usr/srctarxvzflinux-3.0.5.tar.bz2(3)进入目录linux-3.0.5,输入命令makemenuconfiga.fedora和Centos通过yuminstallncurses-devel解决b.Ubuttu和Debian通过sudoapt-getinstalllibncurses5-dev(4)在图形界面中设置config,一般进入GeneralSetup中修改一下内核名称即可(5)编译内核:make–j4bzImage(开4个线程编译,如果是单核的cpu就不用加-j4参数了),编译结束以后,出现Kernel:arch/x86/boot/bzImageisready(#1)则说明内核编译成功(6)编译模块:make–j4modules(时间较长)(7)模块安装:makemodules_install(8)安装内核:makeinstall在高版本中,makeinstall命令会自动生成启动文件,在低内核版本中,需要添加。所以,我们还需要看一下有没有生成启动文件,如果没有,则需要自己手动添加。(9)查看内核是否添加:cat/boot/proc/proc.conf2、创建系统调用的基本步骤(1)在linux-3.2.11/kernel下创建mysyscall.c文件,内容如下:#includelinux/kernel.hasmlinkagelongsys_mysyscall(void){printk(KERN_ALERTThisismysyscall!\n);return0;}(2)在linux-3.2.11/kernel/Makefile中加入:obj-y+=mysyscall.o(3)在linux-3.2.11/include/linux/syscalls.h中加入:asmlinkagelongsys_mysyscall(void);(4)在linux-3.2.11/arch/x86/kernel/syscall_table_32.S(如果是64位机器则32替换为64)中加入:.longsys_mysyscall在linux-3.2.11/arch/x86/ia32/ia32entry.S中加入:.quadsys_mysyscall(5)在linux-3.2.11/arch/x86/include/asm/unistd_32.h中加入:#define__NR_mysyscall349并将#defineNR_syscalls349替换为#defineNR_syscalls350(这里根据实际情况,__NR_mysyscall为现有最大值,NR_syscalls加一即可)(6)重新编译、安装、重启(7)测试查看/proc/kallsyms中是否有mysyscall,如果有,表示符号已经导出。编译运行,输出0即为正确,-1为错误。若运行正确,用dmesg查看,末尾有输出:Thisismysyscall!编译内核成功截图:2、编译模块成功截图:实验中出现的问题:在进行内核编译时,首先遇到的困难就是将缺少的程序补入,但因为本省Ubantu所带的编辑器很不好用,在输入过程中就花费了非常大的时间。但最后经过学长的帮助顺利完成。在编译期间有经历了一个多小时的时间,最后编译成功。在编写调用程序并进行验证的过程中,只能通过自己在网上查找资料,并借鉴同学的作法,最终完成。四、实验体会通过本次实验,我们理解了面向操作命令的接口Shell,学会了简单的shell编码,理解了操作系统调用的运行机制,掌握了创建系统调用的方法。本次实验通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这让我们初步了解了操作系统的生成过程。实验二:进程管理实验一、实验内容1)编制实现软中断通信的程序使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上发出的中断信号(即按delete键),当父进程接收到这两个软中断的某一个后,父进程用系统调用kill()向两个子进程分别发出整数值为16和17软中断信号,子进程获得对应软中断信号,然后分别输出下列信息后终止:Childprocess1iskilledbyparent!!Childprocess2iskilledbyparent!!父进程调用wait()函数等待两个子进程终止后,输入以下信息,结束进程执行:Parentprocessiskilled!!多运行几次编写的程序,简略分析出现不同结果的原因。2)编制实现进程的管道通信的程序使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话:Childprocess1issendingamessage!Childprocess2issendingamessage!而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求:父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。二、实验分析1、进程软中断实现:算法流程图:相关函数:wait()函数wait()函数常用来控制父进程与子进程的同步。在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原来的程序。其调用格式为:#includesys/type.h#includesys/wait.h(pid_t)wait(int*statloc);正确返回:大于0,子进程的进程ID值。等于0,其他。错误返回:等于-1,调用失败。exit()函数exit()函数是进程结束时最常调用的函数,在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。其调用格式为:#includestdio.hvoidexit(
本文标题:操作系统课内实验报告--西安交通大学
链接地址:https://www.777doc.com/doc-1850284 .html