计算机操作系统实验指导232_第1页
计算机操作系统实验指导232_第2页
计算机操作系统实验指导232_第3页
计算机操作系统实验指导232_第4页
计算机操作系统实验指导232_第5页
已阅读5页,还剩227页未读 继续免费阅读

下载本文档

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

文档简介

《计算机操作系统实验指导》第1章实验体系介绍内容操作系统实验的目的操作系统实验体系构成实验报告的撰写要求操作系统实验目的操作系统课程综合了基础理论教学、课程实践教学、最新技术追踪等多项内容,是计算机专业课中非常难学的课程之一操作系统实验可以帮助读者实现理论联系实际,巩固所学的操作系统概念和原理可以增强读者的实践能力,提高读者分析问题、解决问题的能力Linux操作系统的最大特点是源代码开放Linux操作系统成为了操作系统课程学习与实践的良好选择操作系统实验体系的构成基础实验篇本书1-6章操作系统课内实验,用于实践操作系统基本原理和算法的验证与模拟Linux操作系统的使用、进程创建、进程通信、进程同步、内存管理、简单文件系统设计进阶实验篇本书7-12章为“操作系统实践课程”或“操作系统课程设计”等课程服务以Linux内核为实验对象,分析、修改或增加Linux内核功能包括Linux内核编译、系统调用、虚拟内存管理、内核模块编写、文件系统设计、设备管理等实验报告的撰写基础篇实验在实验报告中写出实验步骤、画出程序流程图或给出实验过程、提交源程序和运行结果等进阶篇实验在实验报告中写出实验方法和过程,提交实验过程中的屏幕截图、源代码和运行结果等在“实验结果”部分,需要分析实验的最终结果,以及实验中产生异常的原因在“实验总结”部分,可以给出产生的问题、解决方法以及本次实验收获等《计算机操作系统实验指导》第2章实验环境搭建与使用内容VMWareWorkStation的安装VMWare下新建虚拟机利用VMWare虚拟机安装Linux安装VMWareToolsLinux常用命令Makefile的编写实验2.1Linux常用命令使用实验2.2Linux下C程序的编写1.VMWareWorkStation的安装VMWareWorkStation的下载版本:VMwareWorkstation16Pro下载地址:/cn/products/workstation-pro/workstation-pro-evaluation.html安装过程中的选项激活许可证ZF3R0-FHED2-M80TY-8QYGC-NPKYFYF390-0HF8P-M81RQ-2DXQE-M2UT6ZF71R-DMX85-08DQY-8YMNC-PPHV82.VMWare下新建虚拟机新建虚拟机编辑虚拟机设置内存和处理器的选择内核数设置如何查看计算机有几个核3.利用VMWare虚拟机安装LinuxUbuntuLinux的下载UbuntuLinux下载地址:/download/desktop版本可自行选择以UbuntuLinux20为例编辑虚拟机设置安装Linux映像文件(ubuntu-xxxx-xxxx-xxxx.iso)安装过程中的显示问题进入界面可能会有黑边问题可能会出现点不到屏幕下方的“继续”按钮,拖动窗口也无法上拖的问题,可按住win键+鼠标左键即可拖动启动Linux后,系统界面在VMware全屏下不完全显示4.安装VMWareTools安装VMWareTools复制压缩包至桌面提取压缩包内容在终端打开文件夹输入安装命令安装成功提示最后,重启虚拟机软件或电脑!5.Linux常用命令登录和注销字符工作方式登录:输入用户名和密码注销输入logout使用Ctrl+D键提示符超级用户:#普通用户:$关机与重新启动关机与重新启动的实质是切换运行级别关机命令:init0haltshutdown-h+5重新启动命令:init6rebootshutdown-r+5shutdown命令-k只是警告,不实际关机-r关机后重新启动-h关闭系统命令基本语法$一般shell命令格式:命令[选项][参数]注意元素之间必须有空格!

ls/home8

ls/home3选项:零个、一个或多个

ls–all

/home(长选项)

ls–a/home(短选项)

参数:零个、一个或多个

ls

ls

/home61获得命令帮助man命令格式:man命令名使用上、下箭头键、<PgDn>、<PgUp>翻阅使用Q或q键退出info命令格式:info命令名使用上、下箭头键、<PgDn>、<PgUp>翻阅使用q键退出使用<Ctrl>+h进入info命令的帮助屏幕.

与..

相对路径与绝对路径

cd/etc绝对文件路径定义了在虚拟目录结构中该目录的确切位置,以虚拟目录的根目录开始,相当于目录的全名。绝对文件路径总是以正斜线(/)作为起始,指明虚拟文件系统的根目录

cd../etc相对文件路径允许用户指定一个基于当前位置的目标文件路径单点符(.),表示当前目录;双点符(..),表示当前目录的父目录。常见文件和目录操作命令目录树中走动:cd,pwd,ls创建、删除、移动,复制:touch,mkdir,rmdir,rm,cp,mv文件查看:cat,more,less,head,tail通配符问号(?)代表一个字符;星号(*)代表零个或多个字符;中括号[]标识多个可能的选择,如[a–i];感叹号(!)将不需要的内容排除在外,如[!a]常用的备份压缩命令tar文件,目录打/解包tar-zcvfmyusr.tar.gzmydoc将mydoc目录打包后压缩,调用gzip压缩工具tar-zxvfmyusr.tar.gz解压gzip压缩或解压文件目录,后缀为.gzcompress压缩或解压文件目录,后缀为.Zbzip2压缩或解压文件目录,后缀为.bz2zcat显示压缩的文本文件的内容xz压缩或解压文件目录,后缀为.xz文件权限改变命令chmod更改文件或目录的权限chmoda+xtest.sh为脚本文件test.sh的所有用户增加可执行属性chmodgo–rwxtest取消其他用户对目录test的读、写和执行权限chmod0751file1将文件file1设置为rwxr-x—x权限chown改变文件或目录的属主和属组chmoduser1file1将文件file1的属主改为user1常用的磁盘管理命令df查看文件系统的磁盘空间占用情况du显示目录或文件所占磁盘空间大小mount挂装文件系统umount解挂文件系统与用户有关的命令passwd修改用户口令su切换用户sudo允许普通用户使用超级用户权限执行一些命令6.Linux下C程序的编写从编辑到运行C程序的步骤编写C程序使用Linux下的文本编辑工具,如gedit、emacs、kwrite、vi/vim等保存的文件后缀需为“.c”编译C程序使用gcc编译器运行C程序通过shell执行编译好的可执行文件在shell下输入:

./可执行文件名gcc的使用gcc是运行在Linux操作系统上的一个全功能的ANSIC兼容编译器gcc没有集成的开发环境,但是目前效率最高的C/C++编译器命令格式:

gcc[选项]源文件[目标文件]举例:gcc–ohellohello.cgcc常用编译选项-c:只编译,不链接成可执行文件。编译器只生成.o后缀的目标文件,通常用于不包含主程序的子程序文件。-ofile:确定输出文件的名称为file,该名称不能和源文件同名。若没有该选项,默认生成可执行文件a.out。-Idirname:指定头文件的查找目录,将dirname指定的目录加入程序头文件目录列表中。-Ldirname:指定库文件的查找目录,将dirname对应的目录加入程序函数档案库文件的目录列表中。-lname:在链接过程中,加载名为“libname.a”的函数库(位于系统预设的目录或由-L选项确定的目录下)。-Wall:编译文件时发出所有警告信息。-w:编译文件时不发出任何警告信息make和Makefile文件Linux提供make工具来支持工程项目的编译make根据Makefile/makefile文件的内容来构建程序Makefile文件定义了一系列的规则来告诉make何时以及如何生成或更新目标文件规则的一般形式如下:target:依赖文件列表<TAB>执行命令…Makefile文件的组成部分显式规则:告诉make何时以及如何重新编译或更新一个或多个目标文件变量定义:为一个变量指定一个字符串,在执行make命令时,该变量将被其所代表的字符串替换隐式规则:指出何时以及如何根据名称重新编译或更新一类文件指令:当使用make读取Makefile文件时,指令用来告诉make执行一些特殊活动注释:Makefile文件中的注释以“#”开头,表示该行将在执行时被忽略。Makefile文件示例1main:main.ohello1.ohello2.o gcc–omainmain.ohello1.ohello2.omain.o:main.chello1.hhello2.h gcc–cmain.chello1.o:hello1.chello1.h gcc–chello1.chello2.o:hello2.chello2.h gcc–chello2.cclean: rmmainhello1.ohello2.omain.oMakefile文件示例2obj=main.ohello1.ohello2.o#变量定义main:$(obj)gcc–omain$(obj)hello1.o:hello1.h#自动推导和隐式规则hello2.o:hello2.hclean:rm$(obj)7.实验2.1Linux常用命令使用实验目的了解Linux操作系统的Shell命令格式,熟练掌握常用命令和选项的功能实验内容练习常用的LinuxShell命令及命令选项,包括文件目录命令、备份压缩命令、重定向及管道命令等。要求熟练掌握下列命令的使用。(1)改变及显示目录命令:cd、pwd、ls(2)文件及目录的创建、复制、删除和移动命令:touch、cp、mv、rm、mkdir、rmdir(3)显示文件内容命令:cat、more、less、head、tail(4)文件查找命令:find、whereis、grep(5)文件和目录权限改变命令:chmod(6)备份和压缩命令:tar、gzip、bzip2实验指导开展实验时,要求学生将实验内容中的命令均练习一遍,并查看结果。步骤:(1)打开终端,在提示符下输入命令;(2)执行每一条命令后,分析结果,修改选项后再次执行,查看并记录结果的变化。说明:如果学生已经有Linux操作基础,该实验可以略过也可以由教师课堂演示部分命令的使用8.实验2.2Linux下C程序的编写实验目的掌握Linux下C程序的编写、编译与运行方法。掌握gcc编译器的编译过程,熟悉编译的各个阶段。熟悉Makefile文件的编写格式和make编译工具的使用方法。实验内容练习使用gcc编译器编译C程序并执行,编写Makefile文件,使用make工具编译程序并执行具体要求:(1)编写简单的C程序,功能为在屏幕上输出“Hellogcc!”。利用该程序练习使用gcc编译器的E、S、c、o、g选项,观察不同阶段所生成的文件,即*.c、*.i、*.s、*.o文件和可执行文件。(2)编写一个由头文件greeting.h、自定义函数文件greeting.c、主函数文件myapp.c构成的C程序,并根据这三个文件的依赖关系编写Makefile文件实验指导1对于实验内容(1),可将其分为三个步骤:①创建空文档,修改名称为myhello.c,输入程序代码,保存并退出②打开终端,用gcc命令对myhello.c程序进行分阶段编译③利用ls命令查看编译过程中所产生的各个文件,即myhello.i、myhello.s、myhello.o文件和可执行文件(如myhello.c)实验指导2除3个源代码文件外,最重要的是Makefile的编写:myapp:greeting.omyapp.o gccmyapp.ogreeting.o–omyappgreeting.o:greeting.cgreeting.h gcc–cgreeting.cmyapp.o:myapp.cgreeting.h gcc–cmyapp.cclean: rm–rf*.o最后使用make工具编译程序实验结果

TheEnd!《计算机操作系统实验指导》第3章进程控制和进程调度内容Linux进程介绍Linux进程控制函数介绍实验3.1进程的创建Linux进程调度实验3.2进程的调度Linux进程介绍Linux进程(1)交互进程:由一个shell启动的进程。交互进程既可在前台运行,也可以在后台运行,前者称为前台进程,后者称为后台进程。(2)批处理进程:这种进程和终端没有联系,是一个进程系列,由多个进程按照指定的方式执行。(3)守护进程(Daemon):运行在后台的一种特殊进程,它在系统启动时启动,并在后台运行。LinuxPCBC结构:task_struct

pidt_pid;/*processidentifier*/

longstate;/*stateoftheprocess*/

unsignedinttime_slice/*schedulinginformation*/

structtask_struct*parent;/*thisprocess’sparent*/

structlist_headchildren;/*thisprocess’schildren*/

structfiles_struct*files;/*listofopenfiles*/

structmm_struct*mm;/*addressspaceofthisprocess

……Linux进程状态运行态(TASK_RUNNING):进程准备运行,或正在运行可中断等待态(TASK_INTERRUPTIBLE):进程等待特定事件可中断等待态(TASK_UNINTERRUPTIBLE):进程处于等待状态,但是此刻进程是不可中断的僵尸态(TASK_ZOMBIE):进程已经停止运行,但在内存仍有结构(task_struct)停止态(TASK_STOPPED/

TASK_TRACED):进程暂停状态Linux三种资源拷贝方式共享共享同一资源,如虚存空间、文件等。仅增加有关描述符的用户计数器。直接拷贝 相同的结构,原样复制。COW(CopyOnWrite,写时拷贝)

在需要的时候才复制。创建进程的系统调用Linux提供了三个创建进程的系统调用:fork()

用于普通进程的创建,采用COW方式。vfork()

完全共享的创建,共享同一资源。clone()

由用户指定创建的方式。Linux进程控制函数进程创建——fork()(1)fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程两个进程可以做完全相同的事,根据初始参数或者传入的变量不同,两个进程也可以做不同的事。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。fork()函数(2)fork()的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

1)(>0)在父进程中,fork返回新创建子进程的进程ID;

2)(=0)在子进程中,fork返回0;

3)(<0)如果出现错误,fork返回一个负值;fork()出错可能有两种原因当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。系统内存不足,这时errno的值被设置为ENOMEM。进程标识符管理intgetpid(); //取得当前进程的标识符(进程ID)。intgetppid(); //取得当前进程的父进程ID。intgetpgrp(); //取得当前进程的进程组标识符。intgetpgid(intpid); //将当前进程的进程组标识符改为当前进程的进程ID,使其成为进程组首进程,并返回这一新的进程组标识符。加载新的进程映像——exec函数族(1)创建的进程往往希望它能执行新的程序,在Linux中,进程创建和加载新进程映像是分离操作的。在Linux中,当创建一个进程后,通常使用exec系列函数将子进程替换成新的进程映像。注意:Linux中并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:#include<unistd.h>intexecl(constchar*path,constchar*arg,...);intexeclp(constchar*file,constchar*arg,...);intexecle(constchar*path,constchar*arg,...,char*constenvp[]);intexecv(constchar*path,char*constargv[]);intexecvp(constchar*file,char*constargv[]);intexecve(constchar*path,char*constargv[],char*constenvp[]);其中,只有execve()是真正意义上的系统调用,其它都是在此基础上经过包装的库函数exec函数族(2)exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样。wait()/waitpid()函数作用:父进程查询子进程状态#include<sys/types.h>

#include<sys/wait.h>

pid_twait(int*status);pid_twaitpid(pid_tpid,int*status,intoptions);进程一旦调用了wait(),就立即阻塞自己,由wait()自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸态的子进程,wait()就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait()就会一直阻塞在这里,直到有一个出现为止。wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID当父进程没有使用wait()函数等待已终止的子进程时,子进程就会进入一种无父进程清理自己尸体的状态,此时的子进程就是僵尸进程,不能在内核中清理尸体的情况实验3.1进程的创建实验目的(1)加深对进程概念的理解,进一步认识并发执行的实质。(2)掌握Linux操作系统中进程的创建和终止操作。(3)掌握在Linux操作系统中创建子进程并加载新映像的操作。实验3.1实验内容(1)编写一个C程序,并使用系统调用fork()创建一个子进程。要求如下:①在子进程中分别输出当前进程为子进程的提示、当前进程的PID和父进程的PID、根据用户输入确定当前进程的返回值、退出提示等信息。②在父进程中分别输出当前进程为父进程的提示、当前进程的PID和子进程的PID、等待子进程退出后获得的返回值、退出提示等信息。(2)编写另一个C程序,使用系统调用fork()以创建一个子进程,并使用这个子进程调用exec函数族以执行系统命令ls。实验3.1实验指导本实验主要目的是学会在Linux下使用fork()创建进程,并验证fork()的返回值。首先在主程序中通过fork()创建子进程,并根据fork()的返回值确定所处的进程是子进程还是父进程,然后分别在子进程和当前进程(父进程)中调用getpid()、getppid()、wait()等函数以完成实验内容(1)实验内容(2)的主要目的是学会在Linux下使用fork()创建进程、并使用exec族函数来加载新进程的映像。同时,也可以试验wait()函数的作用。实验3.1实验内容(2)示例代码#include<stdio.h>#include<unistd.h>#include<sys/types.h>intmain(){pid_tpid;

pid=fork();/*创建子进程*/ if(pid<0){/*创建失败*/ fprintf(stderr,"ForkFailed"); return1; } elseif(pid==0){/*子进程*/execlp(“/bin/ls”,“ls”,NULL);/*装载子进程映像ls命令*/ } else{/*父进程*/

wait(NULL);/*父进程等待子进程运行完毕*/ printf("ChildComplete"); }return0;}Linux进程调度Linux进程调度Linux中有一个总的调度结构,称之为调度器类(schedulerclass)允许不同的可动态添加的调度算法并存,总调度器根据调度器类的优先顺序,依次挑选调度器类中的进程进行调度。确定调度器类后,再使用该调度器类的调度算法(调度策略)进行内部调度。调度器类的优先级顺序为:

Stop_Task>Real_Time>Fair>Idle_Task其中,Fair和Real_time最常用,分别采用CFS(完全公平调度算法)调度算法的默认调度类和实时调度类Linux进程调度实验3.2进程调度算法的模拟实验3.2进程调度实验实验目的(1)加深对进程概念的理解,明确进程和程序的区别(2)深入理解系统如何组织进程(3)理解常用进程调度算法的具体实现实验内容

编写C程序模拟实现单处理机系统中的进程调度算法,实现对多个进程的调度模拟,要求采用常见进程调度算法(如先来先服务、时间片轮转和优先级调度等算法)进行模拟调度。实验3.2实验指导(1)数据结构设计PCB:结构体就绪队列:链表,每个节点为进程PCB进程状态调度算法设计具体调度算法:FCFS、SJF、PR涉及多种操作:排序、链表操作程序输出设计调度进程的顺序、每个进程的起始时间、终止时间等CPU每次调度的过程实验3.2实验指导(2)基于动态优先数的进程调度算法(示例代码)优先数大者优先,且优先数每运行一个时间单位降低一级(即优先数=优先数-1)进程的优先数及需要的运行时间事先人为地指定,以1个CPU时间单位进行计算进程状态:W(就绪态)、R(运行态)、F(完成态)输出:每进行一次调度程序都输出一次运行进程和就绪队列中的所有进程信息实验3.2实验结果《计算机操作系统实验指导》第4章进程通信与进程同步内容Linux进程通信机制介绍实验4.1进程通信实验Linux进程同步介绍实验4.2进程同步实验Linux进程通信(IPC)机制介绍LinuxIPC简介(1)管道(Pipe)及有名管道(namedpipe):最古老的进程间通信方式,通过管道文件,将读进程和写进程连接在一起,实现两个进程之间的通信无名管道:有亲缘关系的父子进程或兄弟进程间的通信有名管道:允许无亲缘关系的任意两个进程间进行通信消息队列(报文队列):消息队列是消息的链接表。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点SystemV消息队列、Posix消息队列共享内存:使得多个进程可以访问同一块内存空间,是最快的IPC形式往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥POSIX共享内存、SystemV共享内存LinuxIPC简介(2)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段POSIX信号量和SystemV信号量套接字(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。Linux支持多种类型的套接字。信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生(软中断)除用于进程间通信外,进程还可以发送信号给进程本身支持Unix早期信号语义函数sigal()和符合Posix.1标准的信号函数sigaction()共享内存允许两个不相关的进程访问同一个逻辑内存。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址。优点:①使用方便,函数的接口简单;②数据的共享是直接访问内存,加快了程序的效率;③不要求通信的进程有一定的父子关系缺点:共享内存没有提供同步的机制,需要借助其他的手段(信号量)来进行进程间的同步SystemV共享内存操作函数#include<sys/shm.h>创建共享内存int

shmget(key_t

key,

size_t

size,

int

shmflg);

把共享内存连接到当前进程的地址空间void

*shmat(int

shm_id,

const

void

*shm_addr,

int

shmflg);

将共享内存从当前进程中分离int

shmdt(const

void

*shmaddr);

控制共享内存int

shmctl(int

shm_id,

int

command,

struct

shmid_ds

*buf);

SystemV消息队列(1)消息队列是由一条由消息连接而成的链表,是消息的链式队列,它保存在内核中,通过消息队列的引用标识符来访问。信息被放置在一个预定义的消息结构中,进程生成的消息指明了该消息的类型,并把它放入一个由系统负责维护的消息队列中去。访问消息队列的进程可以根据消息的类型,有选择地从队列中遵照FIFO原则读取特定类型的消息。SystemV消息队列(2)#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>#include<sys/ipc.h>key_tftok(constchar*pathname,intproj_id);//根据关键字生成标识符intmsgget(ket_tkey,intmsgflg);//打开或创建消息队列intmsgsnd(intmsqid,structmsgbuf*msgp,size_tmsgsz,intmsgflg);//发送消息intmsgrcv(intmsqid,structmsgbuf*msgq,size_tmsgsz,longmsgtype,intmsgflg);//接收消息intmsgctl(intmsgqid,intcmd,structmsqid_ds*buf);//消息队列的属性控制实验4.1两个进程相互通信实验4.1实验目的和实验内容实验目的(1)理解进程间通信的概念和方法。(2)掌握常用的Linux进程间通信的方法。实验内容(1)编写C程序,使用Linux中的IPC机制,完成“石头、剪子、布”的游戏。(2)修改上述程序,使之能够在网络上运行该游戏。实验4.1实验指导(1)可以创建三个进程:一个进程为裁判进程,另外两个进程为选手进程。可将“石头、剪子、布”这三招定义为三个整型值,胜负关系为:石头>剪子>布>石头。选手进程按照某种策略(例如,随机产生)出招,交给裁判进程判断大小。裁判进程将对手的出招和胜负结果通知选手。比赛可以采取多盘(如100盘)定胜负,由裁判宣布最后结果。每次出招由裁判限定时间,超时判负。每盘结果可以存放在文件或其他数据结构中。比赛结束,可以打印每盘的胜负情况和总的结果。实验4.1实验指导(2)

具体的实验步骤包括:设计表示“石头、剪子、布”的数据结构,以及它们之间的大小规则;设计比赛结果的存放方式;选择IPC的方法;根据你所选择的IPC方法,创建对应的IPC资源;完成选手进程;完成裁判进程。实验4.1实验指导(3)使用随机数函数rand()模拟出拳信息使用时间作为种子srand()时间需要岔开,否则产生的随机数会相同srand((unsigned)time(0)*3000);srand((unsigned)time(NULL)*i);管理消息队列命令ipcs–q //查看消息队列ipcrm–q //删除消息队列实验4.1实验指导4针对实验内容(1)可以采用多种IPC机制,如管道、消息队列、共享内存在编写程序时,有两种模式编写1个C程序,然后在该程序中创建2个子进程,分别模拟裁判和2个选手,运行时只需1个shell编写3个C程序,分别模拟裁判和2个选手,运行时可打开3个shell同时运行针对实验内容(2),可以使用socket()编程,编写三个C程序分别代表裁判和两个选手。Linux进程同步Linux进程/线程同步简介互斥锁:保证资源独占自旋锁:与互斥量类似,但是等待自旋锁时,进程不会释放CPU,而是一直占用CPU。条件变量:等待和通知,一般与互斥锁合用读写锁:与互斥锁类似,不过读写锁允许更高的并行性记录锁(文件锁):在读写锁的基础上进一步细分被锁对象的粒度信号量:条件变量的升级版Linux信号量机制POSIX信号量有名信号量:基于内存的信号量常用于多线程间的同步,也可用于相关进程间的同步用于进行进程同步时,需要放在进程间的共享内存区中无名信号量:通过IPC名字进行进程间的同步特点是把信号量值保存在文件中既可用于线程,也可用于相关进程,甚至是不相关的进程SystemV信号量使用相对复杂在内核中维护POSIX信号量操作函数#include<semaphore.h>SystemV信号量操作#include<sys/sem.h>intsemget(key_tkey,intnum_sems,intsem_flags);intsemctl(intsem_id,intsem_num,intcmd,unionsemunarg);intsemop(intsem_id,structsembuf*sops,size_tnsops);使用步骤:使用semget()函数创建或获取信号量。不同进程通过使用同一个信号量键值来获得同一个信号量。使用semctl()函数的SETVAL操作初始化信号量。使用semop()函数进行信号量的PV操作,这是实现进程同步或互斥的核心工作。如果不需要信号量,则从系统中删除它,此时使用shmctl()函数的IPC_RMID操作。实验4.2进程同步实验实验4.2实验目的加强对进程同步和互斥的理解,学会使用信号量解决资源共享问题。熟悉Linux进程同步原语。掌握信号量wait/signal原语的使用方法,理解信号量的定义、赋初值及wait/signal操作实验4.2实验内容

编写程序,使用Linux操作系统中的信号量机制模拟实现生产者-消费者问题。设有一个生产者和一个消费者,缓冲区可以存放产品,生产者不断生成产品放入缓冲区,消费者不断从缓冲区中取出产品,消费产品。实验4.2实验指导(1)示例代码设计:使用两个线程来模拟生产者和消费者使用pthread库提供的线程操作,需要包含头文件pthread.h使用POSIX的无名信号量机制,需要包含头文件semaphore.h实验4.2实验指导(2)向缓冲区写产品buffer=(char*)malloc(MAX); //给缓冲区分配内存空间fgets(buffer,MAX,stdin); //输入产品至缓冲区从缓冲区读产品printf("readproductfrombuffer:%s",buffer);//从缓冲区中取出产品memset(buffer,0,MAX); //清空缓冲区线程创建、等待线程结束ret=pthread_create(&id_producer,NULL,producer,NULL);//创建生产者线程ret=pthread_create(&id_consumer,NULL,consumer,NULL);//创建消费者线程pthread_join(id_producer,NULL); //等待生产者线程结束pthread_join(id_consumer,NULL); //等待消费者线程结束实验4.2实验结果注意:pthread库并非Linux操作系统的默认库,编译时需加上-lpthread选项,以调用该链接库

gcc*.c–lpthread《计算机操作系统实验指导》第5章内存管理内容Linux内存管理简介内存操作函数简介实验5.1动态分区分配方式的模拟实验5.2页面置换算法的模拟Linux内存管理简介物理内存管理器:负责物理内存的分配与回收,以页为单位实施管理,目的是提高性能,减少碎片。虚拟内存管理器:它在物理内存管理器的基础上,通过页目录、页表和交换机制,为系统中的每个进程模拟了一个大小为4G的虚拟地址空间。内核内存管理器:负责内核中小内存的分配和回收。内核虚拟内存管理器:为了满足内核对大内存的需求,利用虚拟内存管理的思想,在内核虚拟地址空间实现内核虚拟内存管理。用户空间内存管理器:负责进程用户态虚拟内存的动态分配和回收,它管理的内存在进程的堆中。内存操作函数1.内存分配函数alloc()、calloc()、malloc()和relloc()2.内存映射函数mmap()3.取消映射函数munmap()4.释放内存函数free()5.取得内存分页大小getpagesize()实验5.1动态分区分配方式模拟实验目的(1)掌握动态分区分配方式使用的数据结构和分配算法(2)进一步加深对动态分区分配管理方式及其实现过程的理解实验内容

编写C语言程序,模拟实现首次/最佳/最坏适应算法的内存块分配和回收,要求每次分配和回收后显示出空闲分区和已分配分区的情况。假设初始状态下,可用的内存空间为640KB。实验5.1实验指导数据结构设计已分配分区表、空闲分区表分配算法设计首次适应、最佳适应、最差适应分配算法根据分配算法决定空闲分区表的排序回收算法设计考虑回收区所属的四种情况,有上空分区无下空分区、无上空分区有下空分区、上下分区都为空分区,上下都无空分区,根据情况来决定回收区的处理。实验5.1实验结果假设下列作业请求序列(1)作业1申请130KB(2)作业2申请60KB(3)作业3申请100KB(4)作业2释放60KB(5)作业3释放100KB(6)作业1释放130KB实验5.2页面置换算法模拟实验目的(1)理解虚拟内存管理的原理和技术(2)掌握请求分页存储管理的常用理论——页面置换算法(3)理解请求分页中的按需调页机制实验内容

设计一个虚拟存储区和内存工作区,并使用下述常用页面置换算法计算访问命中率。(1)先进先出算法(FIFO)(2)最近最少使用算法(LRU)(3)最优置换算法(OPT)实验5.2实验要求(1)通过随机数产生一个指令序列,共320条指令。(2)将指令序列转换成页面序列。①页面大小为1KB;②用户内存容量为4~32页;③用户虚存容量为32KB。④在用户虚存中,按每页存放10条指令排列虚存地址,即320条指令存在32个页面中。(3)计算并输出不同置换算法在不同内存容量下的命中率。命中率计算公式为:

命中率

=1–页面失效次数/页面总数实验5.2实验指导(1)使用随机函数srand()和rand()随机产生指令序列①50%的指令是顺序执行的②25%的指令是均匀分布在前地址部分③25%的指令是均匀分布在后地址部分(2)将指令序列变换成相应的页面序列(3)设计页面类型、页面控制结构等数据结构(4)计算使用指定页面置换算法时的命中率实验5.2实验结果当内存页面比较少的时候,访问命中率不高随着内存页面的增多,访问命中率开始提高《计算机操作系统实验指导》第6章简单文件系统设计内容Linux文件目录简介文件操作函数介绍实验6.1文件备份实验实验6.2简单文件系统的模拟Linux文件目录简介Linux文件系统类型Linux文件目录简介文件操作函数简介常用文件操作函数介绍Linux系统调用open():打开文件close():关闭文件read():从文件读数据write():向文件写数据lseek():定位文件指针C语言库函数Fopen()、fclose()、fread()、fwrite()、fseek()等实验6.1文件备份实验实验6.1实验目的和实验内容实验目的(1)熟悉Linux文件系统的文件和目录结构。(2)掌握文件系统的基本特征。(3)掌握常用的文件操作函数。实验内容编写C程序,模拟实现Linux文件系统的简单I/O流操作:备份文件,将源文件source.dat备份为target.dat文件。要求:(1)使用C库函数实现文件备份(2)使用系统调用函数实现文件备份实验6.1实验指导(1)对于实验要求(1),涉及的C库函数有fopen()、fclose()、fread()和fwrite(),并需要经过以下步骤:(1)使用fopen()函数以只读方式打开想要备份的源文件source和以只写方式打开想要写入内容的目标文件target。(2)使用fread()循环读取源文件一个缓冲区大小的内容,使用fwrite()将内容写入目标文件。(3)读取与写入完毕,使用fclose()关闭读写文件流。实验6.1实验指导(2)对于实验要求(2),涉及的Linux相关系统调用有有open()、close()、read()和write(),并需要经过以下步骤:(1)使用open()系统调用函数以只读方式打开想要备份的源文件source和以只写方式打开想要写入内容的目标文件target。(2)使用read()循环读取源文件一个缓冲区大小的内容,使用write()将内容写入目标文件。(3)读取与写入完毕,使用close()关闭读写文件流。实验6.1实验结果实验6.2简单文件系统的模拟实验6.2实验目的理解文件存储空间的管理、文件的物理结构和目录结构以及文件操作的实现。加深对文件系统内部功能和实现过程的理解。2019实验6.2实验内容模拟实现一个简单的二级文件管理系统,要求做到以下几点:(1)可以实现常用文件目录和文件操作,如:login用户登录dir列文件目录create创建文件delete删除文件open打开文件close关闭文件read读文件write写文件(2)列目录时要列出文件名、物理地址、保护码和文件长度(3)源文件可以进行读写保护实验6.2设计思路采用两级目录第一级对应于用户账号第二级对应于用户账号下的文件不考虑文件共享、文件系统安全及特殊文件等内容设计时,确定文件系统的数据结构主目录:链表的形式存放子目录:链表的形式存放活动文件:以编号存储于磁盘上,并在目录中进行登记实验6.2主要数据结构(1)磁盘块结构typedefstructdistTable{intmaxlength; //容量intstart; //起始地址intuseFlag; //是否被使用structdistTable*next; //指向下一块的指针}diskNode;实验6.2主要数据结构(2)文件块结构(即FCB)typedefstructfileTable{charfileName[10];//文件名intstrat;//文件在磁盘存储空间的起始地址

intlength;//文件内容长度

intmaxlength;//文件的最大长度

charfileKind[3];//文件的属性——读写方式

structtm*timeinfo;//文件相关的时间信息boolopenFlag;//判断是否有进程打开了该文件

}fileTableN;实验6.2主要数据结构(3)用户文件目录UFDtypedefstructuser_file_directory{structfileTable*file;//文件structuser_file_directory*next;//下一个用户文件目录}UFD;

主文件目录MFDtypedefstructmaster_file_directory{charuserName[10];//用户账号charpassword[10];//用户密码UFD*user;//用户文件目录}MFD;实验6.2主要数据结构(4)磁盘块结构#defineMaxDisk512*1024chardisk[MaxDisk];//模拟512K的磁盘存储空间typedefstructdistTable//磁盘块结构体

{intmaxlength;intstart;intuseFlag;structdistTable*next;}diskNode;diskNode*diskHead;实验6.2实验结果《计算机操作系统实验指导》第7章内核编译Linux是当今流行的操作系统之一。由于其源码的开放性,现代操作系统设计的思想和技术能够不断运用于它的新版本中。因此,读懂并修改Linux内核源代码无疑是学习操作系统设计技术的有效方法。Linux内核:内核指的是一个提供设备驱动、文件系统、进程管理、网络通信等功能的系统软件,内核并不是一套完整的操作系统,它只是操作系统的核心。Linux发行版本:一些组织或厂商将Linux内核与各种软件和文档包装起来,并提供系统安装界面和系统配置、设定与管理工具,就构成了Linux的发行版本。Linux内核内核编译方法编译Linux的内核,包括如下几个关键步骤:下载内核源代码Linux受GNU通用公共许可证(GPL)保护,内核源代码是完全开放的,可在Linux的官方网站下载。配置内核源代码配置的作用是精确控制新内核的功能,即控制哪些功能需要编译到内核的二进制映像中。编译内核和模块安装和启动Linux内核注意事项提前检查硬盘空间是否足够,4.16.10版本内核推荐编译空间为30GB。本节介绍主要步骤,实验时请结合参考界面,核对实验步骤和结果是否正确。1、查看内核版本#uname-r使用该命令查看当前内核的版本。例如,4.15.10-33-generitic,说明此时的内核版本为4.15.10。2、下载所需内核版本通过Linux官方网站下载内核,也可以到国内的某些网站进行下载。本课程推荐内核版本:linux-4.16.10。下载后压缩包:linux-4.16.10.tar.gz。3、解压将压缩包解压到/usr/src,例如可使用命令:#tarxflinux-4.16.10.tar.gz-C/usr/src解压完成后跳转至/usr/src,利用ls查看是否成功。内核编译具体步骤演示4、配置内核#makemenuconfig利用该命令打开config菜单来配置哪些需要直接编译进内核,哪些编译成模块,哪些不编译。随后使用save保存对应的配置文件.config。说明:如果出现缺包错误,需要按照错误提示安装所需的包。例如,ncurses库,可使用命令apt-getinstallncurses-devel进行安装。对每个配置选项可通过点击<Select>来选择:<*>或[*]:将该功能编译进内核;[

]:不将该功能编译进内核;[

M]:将该功能编译成可以在需要时动态插入内核的模块。内核编译具体步骤演示5、编译内核#make-jn利用make命令开始编译内核。使用-j选项来多线程处理,可以更有效的利用CPU资源。一台双核的机器上,可以用make-j4,让make最多允许4个编译命令同时执行;四核的机器上,可以用make-j8,让make最多允许8个编译命令同时执行。编译没有出错的界面如左图。注意:该步骤需要较长的编译时间,make-j8预计编译时间30分钟。如果出现缺包错误需根据错误提示安装所缺的包。例如,openssl(#

apt-getinstallopenssl)和libssl-dev(#

apt-getinstalllibssl-dev)。内核编译具体步骤演示内核编译具体步骤演示6、编译和安装模块#makemodules#makemodules_install同样,可以使用-j选项多线程处理。例如,#makemodules-j8。7、安装内核#makeinstall8、重新启动,检查新内核#reboot

重启,以开启新的内核。注意:可能出现短暂死机情况。#uname-r

再次查看内核版本,检查是否成功。安装内核步骤成功界面重新查看内核版本常见问题及解决方案编译过程需要细心和耐心,如果出现问题,善用搜索工具查找原因。以下是一些经常出现的问题和一些解决方案,请参考。注意需要提前在“软件与更新”配置页中将更新权限打开,否则出现无法定位的错误。由于Ubuntu使用apt来管理软件包,apt可以将软件库存储在/etc/apt/sources.list和/etc/apt/sources.list.d/目录中带.list后缀的文件中。可以使用命令mansources.list来查看apt的完整存储机制。通过编辑这些文件,可以添加、删除、或者临时关闭某些软件库。也可以通过Ubuntu的图形化界面在属性页通过勾选的方式进行调整。若不安装ncurses直接使用命令makemenuconfig,可能会报缺少ncurses组件的错误,需按照错误提示安装对应的包。例如:#apt-getinstallncurses-devel。如果系统提示缺少依赖的包,请根据错误提示进行安装。例如:#apt-getinstalllibncurses5-devmake过程中也可能出现缺包错误,可能涉及openssl和libssl-dev。可利用下列命令安装。#apt-getinstallopenssl和#apt-getinstalllibssl-dev。编译前一定要注意给出足够的硬盘空间,否则会出现“磁盘空间不足”的错误。必须清理出足够的空间(4.16.10版本的内核推荐25-30GB,建议30GB以上)。重启需要比较长的时间,和所用设备有关,如果出现长时间宕机现象,可以耐心等待,如果超过半个小时候没有响应再考虑编译失败。如果确实重启失败了,说明内核崩溃了。可能原因是编译过程中出现错误或内核本身有问题等,可以更换内核版本重新尝试。《计算机操作系统实验指导》第8章系统调用系统调用系统调用(systemcall)是操作系统提供的服务接口,通常以C或C++编写,对某些底层任务(如需直接访问硬件等)可能以汇编语言指令编写。由操作系统实现并提供的所有系统调用所构成的集合即程序接口或应用编程接口(ApplicationProgrammingInterface,API)。也就是说,系统调用是内核提供的功能十分强大的一系列函数。系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,将处理结果返回给应用程序。本章实验的要求是通过两种方法添加一个不用传递参数的系统调用,其功能是简单地输出一个字符串。添加系统调用的方法添加系统调用有两种方法。一种是编译内核法,一种是内核模块法。编译内核法:(1)添加系统调用号,系统会根据这个号找到syscall_table中的相应表项。具体做法是在syscall_64.tbl文件中添加系统调用号和调用函数的对应关系。(2)实现my_syscall,在kernel/sys.c中添加自己的服务函数,然后为该函数在syscalls.h中添加函数声明。(3)完成准备工作之后,就可以编译内核了,编译内核的方法已在第7章介绍,可直接参照。

内核模块法(1)内核模块法其实是系统调用拦截的实现。系统调用服务程序的地址是存放在sys_call_table中,通过系统调用号定位到的系统调用地址,可以通过编写内核模块修改sys_call_table中的系统调用地址为自己定义的函数地址,这样可以实现系统调用的拦截。(2)具体做法就是通过模块加载时,将系统调用表里的某个系统调用号对应的系统调用服务的地址改为自己实现的系统调用服务的地址。使用内核编译法添加系统调用具体的步骤:获取root权限进入kernel目录打开sys.c,并加入如下函数。asmlinkagelongsys_helloworld(void){printk("helloworld!");return1;}4.添加声明#cd/usr/src/linux-4.16.10/arch/x86/include/asm/#vimsyscalls.h在syscalls.h中插入asmlinkagelongsys_helloworld(void);5.加一个系统调用的id#cd

/usr/src/linux-4.16.10/arch/x86/entry/syscalls#vimsyscall_64.tbl该文件有一个系统调用列表,最前面的属性是id,在里面添加自己的系统调用号,修改后保存syscall_64.tbl文件,添加系统调用号示例:333

64

helloworld

sys_helloworld使用内核编译法添加系统调用6.配置内核#cd

/usr/src/linux-4.16.10#sudomakemrproper#sudomakeclean#sudomakemenuconfig7.编译和安装内核(与第7章类似)#sudomake-j8

#sudomakemodules-j8#sudomakemodules_install#sudomakeinstall8.重启系统#uname-r

查看此时的内核版本使用内核编译法添加系统调用为了验证系统调用是否成功,编写验证代码如下。#include<stdio.h>#include<linux/kernel.h>#include<sys/syscall.h>#include<unistd.h>intmain(){longinta=syscall(333);printf("Systemcallsys_helloworldreutrn%ld\n",a);return0;}编译验证代码:#gcchello.c执行验证代码:#./a.out输出“Systemcallsys_helloworldreutrn

1”表示成功调用。也可以通过dmesg查看系统日志,应有输出“helloworld!”使用内核编译法添加系统调用使用内核模块法添加系统调用内核模块法其实是通过内核模块机制对原有系统调用实现拦截。具体的步骤如下:1.编写hello.c文件,示例代码请参考实验指导书。其中,需要说明的是,我们在asmlinkagelongsys_mycall(void)函数中定义自己的系统调用,例如:asmlinkagelongsys_mycall(void)//定义自己的系统调用{

printk("模块系统调用-当前pid:%d,当前comm:%s\n",current->pid,current->comm);

printk("helloworld!\n");

returncurrent->pid;

}代码中,在模块装载staticint__initcall_init(void)时,实现了用自己的系统调用替换原来的系统调用,而在模块卸载staticvoid__exitcall_exit(void)时再将系统调用恢复。2.查询sys_call_table地址步骤1的示例代码hello.c中的sys_call_table地址,需要修改为自己电脑此时显示的地址,查询当前计算机sys_call_table地址的方法如下:利用命令查询sudocat/proc/kallsyms|grepsys_call_table如图中的执行结果,我们得到sys_call_table地址:ffffffffabe001a0

3.编写Makefile文件,可参考实验指导书中的内容。4.编译并装入模块#

sudomake

//编译#

sudoinsmodhello.ko

//装入模块#

lsmod

//该命令查看所有模块,用以检查hello是否被装入系统#

sudo

rmmod

hello.ko

//卸载模块使用内核模块法添加系统调用为了验证系统调用是否成功,编写验证代码进行验证。创建测试程序test.c,以测试新增的系统调用是否可以正常工作。测试程序示例代码请参照实验指导书。其中主函数中,通过syscall(223);测试223号系统调用,并将返回值输出。intmain(){unsignedlongx=0;x=syscall(223);

//测试223号系统调用printf("syscallresult:%ld\n",x);return0;}编译、运行测试程序#gcc-otesttest.c#./test测试结果示例:控制台输出:syscallresult:6426同时,可以利用dmesg命令查看系统日志输出。#dmesg|tail系统日志输出,包括载入模块,调用系统调用和卸载模块使用内核模块法添加系统调用《计算机操作系统实验指导》第9章虚拟内存管理虚拟内存管理虚拟内存是操作系统内存管理的一种技术,它使得进程不必完全处于内存。进程认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。这种方案的优点是程序可以大于物理内存。目前,大多数操作系统都使用了虚拟内存技术。由于进程线性地址空间里的页面不必常驻内存,在执行一条指令时,如果要访问的页没有在内存中,那么停止该指令的执行,并产生一个页不存在的异常,对应的故障处理程序可通过从外存加载该页的方法来排除故障,即缺页中断处理。中断处理之后,原先引起的异常的指令就可以继续执行。本章实验的目标是复习虚拟内存技术、缺页中断等知识,并统计从当前时刻起一段时间内发生的缺页中断次数。统计系统缺页次数统计一段时间内的缺页次数统计系统缺页次数本实验采用修改内核源代码的方法来统计系统缺页次数,因此,涉及到相关内核源代码的修改、内核的重新编译、统计缺页次数的输出等内容。具体步骤如下:1.在内核源码中找到include/linux/mm.h文件,声明变量pfcount,用于统计缺页次数。2.在/arch/x86/mm/fa

温馨提示

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

评论

0/150

提交评论