操作系统实验报告.docx
- 文档编号:26593472
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:24
- 大小:909.79KB
操作系统实验报告.docx
《操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《操作系统实验报告.docx(24页珍藏版)》请在冰豆网上搜索。
操作系统实验报告
课程设计报告
课程名称:
操作系统
专业班级:
学号:
姓名:
报告日期:
指导老师:
计算机科学与技术学院
1实验一
1.1实验内容与要求3
1.2实验知识准备3
1.3算法设计及分析4
1.3.1文件拷贝4
1.3.2分窗口显示三进程5
1.4实验步骤5
1.5源程序及注释5
1.6程序测试与结果5
1.6.1文件拷贝5
1.6.1分窗口显示三进程5
2实验二
2.1实验内容与要求6
2.2实验知识准备6
2.3算法设计7
2.4实验步骤7
2.5程序测试与结果8
3实验三添加字符设备驱动
3.1实验目的9
3.2实验内容9
3.3实验知识准备9
3.4算法设计10
3.5实验步骤10
3.6程序测试及结果11
4实验四linux的proc文件系统
4.1实验内容与要求12
4.2实验知识准备12
4.3算法设计12
4.4实验步骤13
4.5程序测试及结果13
5实验体会
实验一
1.1实验内容与要求
掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。
A,编一个C程序,其内容为实现文件拷贝的功能;
B,编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。
要求用到Linux下的图形库。
实验知识准备
1.2.1Linux系统的相关知识
Linux文件系统目录结构:
/dev:
dev是device(设备)的缩写。
这个目录下是所有Linux的外部设备,在Linux中设备和文件是用同种方法访问的。
例如:
/dev/hda代表第一个物理IDE硬盘;
/etc:
这个目录用来存放系统管理所需要的配置文件和子目录;
/lib:
这个目录里存放着系统最基本的动态链接共享库,几乎所有的应用程序都须要用到这些共享库;
/usr:
这是最庞大的目录,我们要用到的应用程序和文件几乎都存放在这个目录下。
其中包含以下子目录:
/usr/include:
Linux下开发和编译应用程序需要的头文件,在这里查找;
/usr/lib:
存放一些常用的动态链接共享库和静态档案库;
/usr/local:
这是提供给一般用户的目录,在这里安装软件最适合;
/usr/man:
帮助文档的存放目录;
/usr/src:
由rpm安装的Linux开放的源代码就存在这个目录。
Linux内核源程序的文件组织
核心源程序的文件按树形结构进行组织,简要介绍目录结构如下:
arch:
arch子目录包括了所有和体系结构相关的核心代码。
它的每一个子目录都代表一种支持的体系结构,例如i386就是关于intelcpu及与之相兼容体系结构的子目录,PC机一般都基于此目录;
drivers:
放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录,如/block下为块设备驱动程序;
include:
include子目录包括编译核心所需要的大部分头文件。
与平台无关的头文件在include/linux子目录下,与intelcpu相关的头文件在include/asm-i386子目录下;
init:
这个目录包含核心的初始化代码(注:
不是系统的引导代码),包含两个文件main.c和version.c,这是研究核心如何工作的一个非常好的起点;
mm:
这个目录包括所有独立于cpu体系结构的内存管理代码,如页式存储管理内存的分配和释放等,而和体系结构相关的内存管理代码则位于arch/*/mm/;
kernel:
主要的核心代码,此目录下的文件实现了大多数Linux系统的内核函数,其中最重要的文件当属进程调度sched.c,同样,和体系结构相关的代码在arch/*/kernel中。
Linux的图形编程:
Gtk(具有OO特色的C语言框架)
GTK(GIMPToolkit):
控件、消息处理器和回调函数;利用控件可以实现一些图形的显示,比如显示窗口等等;消息处理器等待事件的发生(关闭窗口、点击按钮等),并捕获该信号,告诉GTK程序应该调用哪个回调函数进行相应的处理,并在终端中显示结果。
编写gtk程序:
1初始化Gtk;2建立控件;3登记消息与消息处理
函数;4执行消息循环函数gtk_main();只有gtk_main_quit()函数才能停止Gtk+的执行,从而最终退出应用程序。
把gtk_main_quit()函数放在某个消息处理函数之中
编译和执行gtk程序:
程序中用到Gtk+函数或定义的每一部分必须包含
gtk/gtk.h文件,此外,还必须连接若干库。
gcchello.c-ohello`gtk-config--cflags``gtk-config--libs`反引号(在键盘上位于字符1的左边),chmod-777hello”将hello设定为可执行的文件。
1.2.3Linux编程环境
函数库:
glibc:
要构架一个开发环境,glibc是必不可少的,它是Linux下C的主要函数库。
编译器:
gcc(GNUCCompiler)是GNU推出的功能强大、性能优越的多平台编译器,gcc编译器能将C、C++语言源程序、汇编程序和目标程序编译、连接成可执行文件.
系统头文件:
glibc_header,缺少了系统头文件,就会无法编译C源程序
其他软件:
vi,rpm,tar,binutils,make
算法设计及分析
1.3.1文件拷贝
设计思路:
A,用open函数打开源文件,并做出错处理;B,用open函数
以创建的方式打开目的文件,并作出错处理;C,用read函数循环从源文件中读出BUFFER_SIZE个字节的字符,wirte函数写入目的文件,至文件全部写完;D,关闭源文件和目的文件。
分窗口显示三进程
软件实现:
用gtk实现图形界面。
设计思路:
main函数中,用fork创建子进程和父进程,子进程实现./time可执行文件,父进程再次调用fork创建二个进程。
再为每个进程设计一个弹框
1.4实验步骤
这个实验比较简单,首先编写源程序,后编译,再执行。
需要注意的是,显示三个进程的实验编译时,使用的命令为:
假设源程序名为“col.c”
gcc`pkg-config--cflags--libsgtk+-2.0`col.c-ocol
而且首先分别编译好三个子程序,再编译main程序,最后运行main可执行文件。
这里因为使用了gtk,故编译的命令和以前直接编译有所不同。
1.5源程序及注释
见电子档
1.6程序测试及结果
实验二
2.1实验内容与要求
掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。
另编写一个应用程序,调用新增加的系统调用。
(1)实现的功能是:
文件拷贝;
(2)实现的功能是:
P、V操作。
实验知识准备
2.2.1系统调用
Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。
用户可以通过系统调用命令在自己的应用程序中调用它们。
关键字:
系统调用核心态操作系统核心提供
普通的函数调用用户态函数库或用户自己提供
很多已经被我们习以为常的C语言标准函数,在Linux平台上的实现都是靠系统调用完成的,如open(),close(),malloc(),fork().
2.2.2系统调用工作原理
用户权限不能访问内核所占内存空间,也不能调用内核函数。
进程调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。
在IntelCPU中,这个由中断INT0x80实现。
(与DOS功能调用int0x21很相似)跳转到的内核位置叫做sysem_call。
检查系统调用号,这个号码代表进程请求哪种服务。
然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。
接着,就调用函数,等返回后,做一些系统检查,最后返回到进程(或到其他进程,如果这个进程时间用尽)。
系统调用号表示数组sys_call_table[]中的位置。
文件../Arch/i386/kernel/entry.S中:
Entry(system_call_table)
3.2.3如何使用系统调用
#include
#include
_syscall1(time_t,time,time_t*,tloc)/*宏,展开后得到time()函数的原型*/
main(){
time_tthe_time;
the_time=time((time_t*)0);/*调用time系统调用*/
printf("Thetimeis%ld\n",the_time);
}
标准的系统调用的形式,宏_syscall1()展开来得到一个函数原型;time.h中
已经用库函数的形式实现了time这个系统调用,省掉了调用_syscall1宏,大多数系统调用都在各种C语言函数库中有所实现,一般情况下,都调用普通的库函数
syscall函数原型为:
其中number是系统调用号,number后面应顺序接上该系统调用的所有参数。
mm_segment_told_fs=get_fs()
set_fs(KERNEL_DS)
2.2.4与系统调用相关的内核代码文件(2.6内核)
/usr/src/linux/include/asm-i386/unistd.h
系统调用清单(为每个系统调用分配唯一号码)
/usr/src/linux/arch/i386/kernel/entry.S
包含系统调用和异常的底层处理程序、信号量的识别程序
ret_from_sys_call:
调用和中断的返回点
对sys_call_table[](系统功能调用表)进行初始化
/usr/src/linux/kernel/sys.c系统调用实现代码
/usr/src/linux/arch/i386/kernel/traps.c定义许多出错处理程序
算法设计
这个实验就是实现文件拷贝功能,并将此函数添加入系统功能调用,源码与第一个实验文件拷贝很类似。
不同的是这里是在内核里面编程,与以前有所不同,以前使用的open,close,read,write函数都不可用,这里只能使用sys_open,
sys_read,sys_write等系统函数对文件进程操作,拷贝时的算法与第一个实验都相同。
另外,需要注意的是,使用缓冲区时,还需调用get_fs();set_fs()函数,说明内存地址检查时,不对此处进行检查,否则可能出错。
实验步骤
1,修改/usr/src/linux-2.6.34.14下的Makefile文件,将内核版本
修改成自己的。
我的版本本来就是这个版本,所以不用修改。
2,修改(添加)源代码。
编写加到内核中的源程序,即将要加到一个内核文件中去的一个函数,该
函数的名称应该是新的系统调用名称前面加上sys_标志。
在/usr/src/linux-2.6.32.45/kernel/sys.c文件中添加源代码,如下所示:
3,连接新的系统调用
添加新的系统调用后,下一个任务是使Linux内核的其余部分知道该程序的存在。
为了从已有的内核程序中增加到新的函数的连接,需要编辑两个文件。
首先要修改的文件是unistd.h:
/usr/src/linux-2.6.34.14/arch/x86/include/asm/unistd_32.h
该文件中包含了系统调用清单,用来给每个系统调用分配一个唯一的号码。
然后要修改的文件路径为:
、/usr/src/linux-2.6.34.14/arch/x86/kernel/syscall_table_32.S
该清单用来对sys_call_table[]数组进行初始化。
该数组包含指向内核中每个系统调用的指针。
这样就在数组中增加了新的内核函数的指针。
在终端打开此文件,这里因为字母大小写的缘故出错,终端对字母大小写敏感,故一个字母都不能错,要不就打不开文件,由此可见,细心很必要。
在清单上与系统调用号相对应的位置添加一行:
.longsys_mysyscall
这里,在最后一行添加所需代码。
4,开始对新的内核进行编译
首先需要清空以前的编译信息,避免编译内核时生成的文件不一致。
makemrproper命令清除旧的配置等文件,以免后面出错。
这里又看到:
权限不够也不可,必须用root权限才能使用某些功能。
使用root权限,清除了旧的配置文件。
E,makemenuconfig命令生成配置清单文件。
终端输入命令:
sudomakemenuconfig
原来是ubuntu系统没有ncurses这个库。
解决方法:
终端输入命令:
sudoapt-getinstallncurses-dev安装这个库文件。
curses构成了一个工作在底层终端代码之上的封装,并向用户提供了一个灵活高效的API(ApplicationProgrammingInterface应用程序接口)。
它提供了移动光标,建立窗口,产生颜色,处理鼠标操作等功能。
再次在终端输入命令:
song@song-laptop:
/usr/src/linux-2.6.32.45$sudomakemenuconfig
5,编译新的内核,输入命令:
sudomake–j4;
64参数代表使用4个线程同时编译,这样速度会快点。
过程见下:
此步由makebzImage和makemodules两步组成,两步操作都要等很长时间
7,终端输入命令:
sudomakemodules_install
8,命令:
sudomakeinstall
9mkinitramfs-o/boot/initrd.img-mycall命令生成系统镜像文件。
10,update-grub命令更新启动程序grub,使启动界面上出现新安装的系统。
11,添加一个新的系统启动引导项成功后就可以重启电脑了,重启之后运行测试程序。
2.6程序测试及结果
实验三添加字符设备驱动
3.1实验目的
1.了解Linux下设备驱动程序的原理
2.学习Linux2.6内核下设备驱动程序编写方法
3.掌握用模块方式设计和加载驱动程序的方法
3.2实验内容
(1)增加设备驱动程序:
增加一个新的字符设备驱动程序
(2)以动态方式加载设备驱动程序:
采用动态模块加载方式加载已完成的字符设备驱动程序,并编写应用程序进行测试
3.3实验知识准备
3.3.1相关概念和操作
字符设备:
通过位于/dev目录的文件系统结点来存取,映射为chrdevs向量表中的device_struct条目,大部分字符设备是数据通道,只能顺序存取,直接对设备进行读写操作。
驱动程序加载方式:
常见的驱动程序作为内核模块动态加载(如声卡、网卡等),最基础的驱动程序编译在内核文件中(如CPU、PCI总线、VFS等)
驱动加载时的模块命令
模块加入:
insmodmodulename.ko
查看模块:
lsmod
删除模块:
rmmodmodulename
注册设备:
向系统登记设备及驱动程序的入口点
intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);
若登记成功,返回设备的主设备号,否则,返回一个负值
intregister_blkdev(unsignedintmajor,constchar*name,structfile_operations*fops);
向系统的块设备表登记一个块设备
动态加载—实现机制
init_modules()启动时内核模块的初始化,求出内核符号表中符号的个数
sys_create_module()创建一个新模块,即为新模块分配空间,也是系统调用create_module()在内核的实现函数
sys_init_module():
系统调用init_module()在内核的实现函数
sys_delete_module():
系统调用delete_module()在内核的实现函数
query_module():
查询模块名
request_module():
主动装入内核模块
3.3.2添加设备驱动程序的方法
1)编写设备驱动程序mydev.c
2)设备驱动模块的编译
3)加载设备驱动模块:
insmodmydev.ko
若加载设备驱动模块成功,在文件/proc/devices中能看到新增加的设备,包括设备名mydev和主设备号。
4)生成设备文件:
mknod/dev/testc2540
其中,test为设备文件名,254为主设备号,0为从设备号,c表示字符设备
3.3.3Linux系统采用一组固定的入口点来实现驱动设备的功能
1)open入口点:
打开设备准备I/O操作。
open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。
2)close入口点:
关闭一个设备。
当最后一次使用设备终结后,调用close子程序。
3)read入口点:
从设备上读数据。
4)write入口点:
往设备上写数据。
5)ioctl入口点:
执行读、写之外的操作。
6)select入口点:
检查设备,看数据是否可读或设备是否可用于写数据。
如果设备驱动程序没有提供上述入口点中的某一个,系统会用缺省的子程序来代替。
对于不同的系统,也还有一些其它的入口点。
算法设计
linux内核是一个整体结构,因此向内核添加任何东西.或者删除某些功能,都十分困难。
但模块机制的引入,可以动态的在内核中添加或者删除模块。
模块一旦被插入内核,他就和内核其他部分一样。
故要想在内核中添加一字符设备驱动,便要将设备驱动程序编译成模块,加入内核中。
Linux系统内部定义了很多函数用于模块和设备驱动。
其中,使用insmod来显式加载核心模块,使用rmmod来卸载模块。
同时核心自身也可以请求核心后台进程kerneld来加载与卸载模块。
对于每一个内核模块来说,必定包含两个函数:
intinit_module()这个函数在插入内核时启动,在内核中注册一定的功能函数;intcleanup_module()当内核模块卸载时,调用它将模块从内核中清除。
本次实验的二个此函数分别为:
__initsong_init();__exitsong_exit(),分别初始化和退出模块。
这便可插入了模块。
Linux内核中的设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程。
对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口。
而对于字符设备,添加设备驱动,首先需包含二个基本函数,一个是注册设备函数,register_chrdev(…);另一是卸载设备函数,unregister_chrdev(…)。
其次是编写设备驱动的子函数,即定义并填充结构file_operations的各个域。
本次实验定义了四个子函数,分别为:
song_read,song_write,song_open,song_release.其功能见其名即可知。
函数的具体实现可见源代码。
要添加的内核模块编辑完毕后,便要编辑测试程序了。
测试程序中,使用open函数打开新添加的设备,用read,wirte函数从字符设备中读/写sizeof(buf)个字节(buf是char型的数字)到缓冲区中,便可使用新添的字符设备了。
最后,需要编辑的是Makefile文件了,里面需要添加的是,模块的文件组成及生成的模块名等信息,具体见源程序中的Makefile文件。
F,新添模块成功后,便要测试新的设备驱动是否正确了。
测试程序见4.7.这里不再赘述。
G,模块生成成功后,便要卸载了。
终端输入命令:
sudorm/dev/song_dev
sudormmod-vsong_dev.ko
便可卸载模块了,再次查询设备,验证是否已删除。
输入命令:
sudolsmod查看模块
3.7程序测试及结果
实验四linux的proc文件系统
4.1实验内容与要求
了解和掌握/proc文件系统的特点和使用方法。
了解/proc文件的特点和使用方法
监控系统状态,显示系统中若干部件使用情况
用图形界面实现系统监控状态。
4.2实验知识准备
Linux的PROC文件系统是进程文件系统和内核文件系统的组成的复合体,是将内核数据对象化为文件形式进行存取的一种内存文件系统,是监控内核的一种用户接口.它拥有一些特殊的文件(纯文本),从中可以获取系统状态信息。
(1)系统信息
系统信息,与进程无关,随系统配置的不同而不同。
命令procinfo可以显示这些文件的大量信息。
/proc/cmd/line:
内核启动的命令行/proc/cpuinfo:
CPU信息
/proc/stat:
CPU的使用情况、磁盘、页面、交换、所有的中断、最后一次
的启动时间等。
/proc/meminfo:
内存状态的有关信息。
进程信息:
保存系统中正在运行的每一个用户级进程的信息。
监控系统功能:
通过读取proc文件系统,获取系统各种信息,并以
比较容易理解的方式显示出来。
要求使用GTK+Linux下的c语言开发。
具体包括:
主机名、系统启动时间、系统运行时间、版本号、所有进程信息、CPU类型、CPU的使用率、内存使用率……
其中,在文件/proc/sys/kernel/hostname中,获取并显示主机名;在文件/proc/uptime中获取并显示系统启动的时间和系统到目前为止持续运行的时间;
在文件/proc/sys/kernel/ostype中显示系统的版本号;在文件/proc/cpuinfo中显示cpu的型号和主频大小;/proc/stat显示进程的详细信息,提供杀掉该进程的功能。
在文件/proc/meminfo中显示当前内存使用情况。
4.3算法设计
本实验主要是从proc文件中读出系统的相关信息,并用gtk实现图新界面,显示读出的信息,类似于一个文件管理器。
Gtk的使用在第一个实验中,已经有了一定的了解及认识,但这里比上次实验复杂,应用的构件也多很多,所以要求也高很多。
在文件系统的主窗口中,先创建一名为“song-任务管理器”的顶层窗口window,再在窗口中装入一表格table,表格是为了容纳新的构件。
Table中装入笔记本构件notebook,notebook有四页,每页装入一框架frame。
在Table的左上方,添加一菜单栏,提供“重启,挂起,注销,关机”四个功能,同时在table的最后一栏,显示系统启动时间,运行时间和当前的时间。
Notebook的第零页,名为“source(资源)”,显示内存使用率和cpu使用率。
Cpu使用率从文件/proc/stat中读出,内存使用率由/proc/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 实验 报告