华科操作系统实验报告.docx

上传人:b****6 文档编号:8657288 上传时间:2023-02-01 格式:DOCX 页数:18 大小:197.66KB
下载 相关 举报
华科操作系统实验报告.docx_第1页
第1页 / 共18页
华科操作系统实验报告.docx_第2页
第2页 / 共18页
华科操作系统实验报告.docx_第3页
第3页 / 共18页
华科操作系统实验报告.docx_第4页
第4页 / 共18页
华科操作系统实验报告.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

华科操作系统实验报告.docx

《华科操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《华科操作系统实验报告.docx(18页珍藏版)》请在冰豆网上搜索。

华科操作系统实验报告.docx

华科操作系统实验报告

课程实验报告

课程名称:

操作系统课程设计

专业班级:

学号:

姓名:

指导教师:

报告日期:

计算机科学与技术学院

课程设计任务书

一.课设目的

1.掌握Linux操作系统的使用方法;

2.了解Linux系统内核代码结构;

3.掌握实例操作系统的实现方法。

二.课设内容

1.掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。

(一)编一个C程序,其内容为实现文件拷贝的功能;

(二)编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。

要求用到Linux下的图形库。

gtk/qt

2.掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。

另编写一个应用程序,调用新增加的系统调用(实现的功能为文件拷贝)。

3.掌握增加设备驱动程序的方法。

通过模块方法,增加一个新的设备驱动程序,其功能可以简单(实现字符设备的驱动)。

4.了解和掌握/proc文件系统的特点和使用方法(选做)

(一)了解/proc文件的特点和使用方法

(二)监控系统状态,显示系统中若干部件使用情况

(三)用图形界面实现系统监控状态。

5.设计并实现一个模拟的文件系统(选做)

多用户的多级目录的文件系统设计。

多用户、多级目录、login(用户登录)、系统初始化(建文件卷、提供登录模块)、文件的创建、文件的打开、文件的读、文件的写、文件关闭、删除文件、创建目录(建立子目录)、改变当前目录、列出文件目录、退出。

 

三.课设说明

Linux系统版本:

Fedora5.06.0…

ubuntu10.0411.10

内核版本:

linux-2.6.x

 

四.考核要求

1.必须独立完成课程设计内容,不分小组,不能有相同的拷贝。

2.上机考试:

学生根据老师提出的要求,演示所完成的系统;并回答老师的问题。

3.第三周五下午2:

00全体到实验室做中期检查,只检查1、2题;第四周周五下午2:

00:

最后检查。

按学号次序逐个检查。

4.评分方法:

完成1、2题,得60-65分;

完成1、2、3题,得65-75分;

完成1、2、3、4(5)题,得80--100分;

报告:

10分(倒扣分)

上交:

课程设计报告(打印/电子档),内容包括调试记录和程序清单(附注释)。

第六周五前以班为单位交指导老师。

 

五.参考资料

Linux的“man”帮助!

《Linux内核2.4版源代码分析大全》

《Linux内核源代码分析》

《Linux编程白皮书》

 

课程内容与过程

一.掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。

1)编一个C程序,其内容为实现文件拷贝的功能。

1 任务分析:

在Linux下,如果要编译一个C语言源程序,要使用到gcc编译器。

gcc编译器中,-o选项表示我们要求输出的可执行文件名。

-c选项表示我们只要求编译器输出目标代码,而不必要输出可执行文件。

-g选项表示我们要求编译器在编译的时候提供我们以后对程序进行调试的信息。

知道了这三个选项,我们就可以编译我们自己所写的简单的源程序了。

文件拷贝的C程序主要用到如下几个函数:

●open:

打开文件

open()函数

功能描述:

用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。

所需头文件:

#include,#include,#include

函数原型:

intopen(constchar*pathname,intflags,intperms)

参数:

pathname:

被打开的文件名(可包括路径名如"dev/ttyS0")

flags:

文件打开方式,

O_RDONLY:

以只读方式打开文件

O_WRONLY:

以只写方式打开文件

O_RDWR:

以读写方式打开文件

O_CREAT:

如果改文件不存在,就创建一个新的文件,并用第三个参数为其设置权限

返回值:

成功:

返回文件描述符

失败:

返回-1

 

●close:

关闭文件

close()函数

功能描述:

用于关闭一个被打开的的文件

所需头文件:

#include

函数原型:

intclose(intfd)

参数:

fd文件描述符

函数返回值:

0成功,-1出错

●read:

读操作

read()函数

功能描述:

从文件读取数据。

所需头文件:

#include

函数原型:

ssize_tread(intfd,void*buf,size_tcount);

参数:

fd:

将要读取数据的文件描述词。

buf:

指缓冲区,即读取的数据会被放到这个缓冲区中去。

count:

表示调用一次read操作,应该读多少数量的字符。

返回值:

返回所读取的字节数;0(读到EOF);-1(出错)。

●write:

写操作

write()函数

功能描述:

向文件写入数据。

所需头文件:

#include

函数原型:

ssize_twrite(intfd,void*buf,size_tcount);

返回值:

写入文件的字节数(成功);-1(出错)

2 实现文件拷贝的源程序如下所示:

#include

#include

intmain(intargc,char*argv[])

{

intsfd,tfd,num;

char*buf;

if(argc!

=3)

{

printf("ERROR!

COPYFROMTO\n");

return-1;

}

if((sfd=open(argv[1],O_RDONLY,0))==-1)

{

printf("ERROR,OPENFILEFAILED!

\n");

return-1;

}

if((tfd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666))==-1)

{

printf("TARGETFILEOPENFAIL!

\n");

return-1;

}

while(num=read(sfd,buf,1)>0)

write(tfd,buf,num);

close(sfd);

close(tfd);

exit(0);

}

3 程序运行结果

源程序通过gcc编译器编译后会生成可执行文件1,执行可执行文件1之前,/hukeled目录下的文件a内容如图1所示,文件b内容如图2所示。

图1执行1前文件a中的内容

图2执行1前文件b中的内容

执行1后,目录/hukeled下文件b中的内容如图3所示,由图可知文件a的内容正确无误的拷贝到了文件b中,故程序运行结果正确。

图3执行1后文件b中的内容

同时,源程序还可以实现图片等字符流数据的拷贝。

 

2)编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。

要求用到Linux下的图形库。

1 任务分析:

程序是指令的有序集合,是一个静态概念,其本身并没有任何运行的含义。

而进程是程序在处理机上的一次执行过程,是一个动态概念。

一个程序可能有许多进程,而每一个进程又可以有许多子进程。

为了区分各个不同的进程,系统给每一个进程分配了一个ID(就象我们的身份证)以便识别。

为了充分的利用资源,系统还对进程区分了不同的状态,将进程分为新建、运行、阻塞、就绪和完成五个状态。

当一个进程调用了fork以后,系统会创建一个子进程。

这个子进程和父进程不同的地方只有他的进程ID和父进程ID,其他的都是一样,就像父进程克隆(clone)自己一样。

当然创建两个一模一样的进程是没有意义的。

为了区分父进程和子进程,我们必须跟踪fork的返回值,当fork调用失败的时候(内存不足或者是用户的最大进程数已到)fork返回-1。

否则fork的返回值有重要的作用。

对于父进程fork返回子进程的ID,而对于fork子进程返回0。

我们可以根据这个返回值来区分父子进程。

Qt是一个跨平台的C++图形用户界面库,具有优良的跨平台特性:

1)Qt支持下列操作系统:

MicrosoftWindows95/98,MicrosoftWindowsNT,Linux,Solaris,SunOS,HP-UX,DigitalUNIX(OSF/1,Tru64),Irix,FreeBSD,BSD/OS,SCO,AIX,OS390,QNX等等。

2)面向对象

3)Qt的良好封装机制使得Qt的模块化程度非常高,可重用性较好,对于用户开发来说是非常方便的。

Qt提供了一种称为signals/slots的安全类型来替代callback,这使得各个元件之间的协同工作变得十分简单。

4)丰富的API

5)Qt包括多达250个以上的C++类,还提供基于模板的collections,serialization,file,I/Odevice,directorymanagement,date/time类。

甚至还包括正则表达式的处理功能。

6)支持2D/3D图形渲染,支持OpenGL

7)大量的开发文档

8)XML支持。

在编译qt程序时,需要用到与编译普通程序不同的命令。

比如程序名为hello,则编译过程为:

用qt的工具qmake来生成工程文件:

qmake -project;生成Makefile文件:

qmake hello.pro;接下来就是make;运行程序./hello。

2 程序源代码为:

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

MainWindoww;

w.show();

pid_tp1,p2,p3;

if((p1=fork())==0)

{

execv("/home/hukeled/1.2/2",NULL);

}

elseif((p2=fork())==0)

{

execv("/home/hukeled/1.2/3",NULL);

}

returna.exec();

}

 

二、掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。

另编写一个应用程序,调用新增加的系统调用(实现的功能为文件拷贝)。

1 任务分析:

一般的,进程是不能访问内核的。

它不能访问内核所占内存空间也不能调用内核函数。

CPU硬件决定了这些(这就是为什么它被称作"保护模式")。

系统调用是这些规则的一个例外。

其原理是进程先用适当的值填充寄存器,然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。

在IntelCPU中,这个由中断0x80实现。

硬件知道一旦你跳到这个位置,你就不是在限制模式下运行的用户,而是作为操作系统内核。

进程可以跳转到的内核位置叫做sysem_call。

这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。

然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。

接着,就调用函数,等返回后,做一些系统检查,最后返回到进程(或到其他进程,如果这个进程时间用尽)。

系统调用是应用程序和操作系统内核之间的功能接口,通过系统调用进程可由用户模式转入内核模式。

在内核模式下完成相应的服务之后再返回到用户模式。

系统调用的主要目的是使得用户可以使用操作系统提供的有关设备管理、输入输出系统、文件系统和进程控制、通信以及存储管理等方面的功能,而不必了解系统程序的内部结构和有关硬件细节,从而起到减轻用户负担和保护系统以及提高资源利用率的作用。

本次课设,我通过编译内核的方式,增加了一个系统调用,其功能为文件拷贝。

 

2 添加的系统调用源代码和测试程序

系统调用源代码

asmlinkageintsys_mycall(char*sourceFile,char*destFile)

{

intsource=sys_open(sourceFile,O_RDONLY,0);

intdest=sys_open(destFile,O_WRONLY|O_CREAT|O_TRUNC,0600);

charbuf[4096];

mm_segment_tfs;

fs=get_fs();

set_fs(get_ds());

inti;

if(source>0&&dest>0)

{

do

{

i=sys_read(source,buf,4096);

sys_write(dest,buf,i);

}

while(i);

}

else

{

printk("Error!

");

}

sys_close(source);

sys_close(dest);

set_fs(fs);

return1;

}

 

测试程序源代码

#include

#include

intmain(intargc,char*argv[])

{

syscall(351,argv[1],argv[2]);

return0;

}

3 实验过程与步骤

根据教程

第一步:

(1)获取系统的版本号,使用命令uname-a,获取版本号为3.13.0

(2)下载3.12.39的内核,解压到文件夹/usr/src中,解压命令:

xz–dlinux-3.13.tar.xz

tar–xvflinux-3.13.tar

(3)进入linux-3.13.0目录,清除残留的.config和.o文件,命令:

makemrproper

(4)安装ncurses-5.9:

下载ncurses-5.9,按照安装linux-3.13的方法解压ncurses-5.9到文件来/usr/src中,进入文件夹ncurses-5.9中配置环境:

cdncurses-5.9

./configure

make

makeinstall

(5)makemenuconfig选择编译配置选项。

(6)确定依赖性:

makedep

(7)清理中间文件:

makeclean

(8)生成新内核:

makebzImage

(9)生成modules:

makemodules

(10)安装modules:

makemodules_install

(11)安装内核

makeinstall

(12)重启选用新内核

第二步:

添加自定义系统调用

(1)添加系统调用函数,修改文件:

/kernel/sys.c

asmlinkageintsys_mycall(char*sourceFile,char*destFile)

{

intsource=sys_open(sourceFile,O_RDONLY,0);

intdest=sys_open(destFile,O_WRONLY|O_CREAT|O_TRUNC,0600);

charbuf[4096];

mm_segment_tfs;

fs=get_fs();

set_fs(get_ds());

inti;

if(source>0&&dest>0)

{

do{

i=sys_read(source,buf,4096);

sys_write(dest,buf,i);

}

while(i);

}

else

{

printk("Error!

");

}

sys_close(source);

sys_close(dest);

set_fs(fs);

return1;

}

(2)添加系统调用号,修改文件/arch/x86/syscalls/syscall_64.tbl

351commonmycallsys_mycall

(3)添加声明到头文件,修改文件,/include/asm-generic/syscalls.h

asmlinkageintsys_mycall(char*sourceFile,char*destFile)

(4)重新编译内核,只用第一步中的(8),(11),重启即可。

第三步:

测试函数

代码:

intmain(intargc,char*argv[])

{

syscall(351,argv[1],argv[2]);

return0;

}

 

三、掌握增加设备驱动程序的方法。

通过模块方法,增加一个新的设备驱动程序,其功能可以简单(实现字符设备的驱动)。

1 任务分析:

linxu系统中,在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。

设备驱动程序是内核的一部分,它完成以下的功能:

1.对设备初始化和释放.

2.把数据从内核传送到硬件和从硬件读取数据.

3.读取应用程序传送给设备文件的数据和回送应用程序请求的数据.

4.检测和处理设备出现的错误.

Linux操作系统允许设备驱动程序作为可装载内核模块实现,这也就是说,设备的接口实现不仅可以在Linux操作系统启动时进行注册,而且还可以在Linux操作系统启动后装载模块时进行注册。

总之,Linux操作系统支持多种设备。

2 设备驱动程序代码:

#include"linux/kernel.h"

#include"linux/module.h"

#include"linux/fs.h"

#include"linux/init.h"

#include"linux/types.h"

#include"linux/errno.h"

#include"linux/uaccess.h"

#include"linux/kdev_t.h"

#include"linux/string.h"

#defineMAX_SIZE20

staticintmy_open(structinode*inode,structfile*file);

staticintmy_release(structinode*inode,structfile*file);

staticssize_tmy_read(structfile*file,char__user*user,size_tt,loff_t*f);

staticssize_tmy_write(structfile*file,constchar__user*user,size_tt,loff_t*f);

charmessage[MAX_SIZE]="--congratulations--!

";

staticintdevice_num=0;//设备号

staticintcounter=0;//计数用

staticintmutex=0;//互斥用

staticchar*devName="mydevice";//设备名

//addedbywuyao

intmes_num=0;

chartmp;

//////////////////

structfile_operationspStruct=

{open:

my_open,release:

my_release,read:

my_read,write:

my_write,};

/*注册模块*/

intinit_module()

{

intret;

/*函数中第一个参数是告诉系统,新注册的设备的主设备号由系统分配,

*第二个参数是新设备注册时的设备名字,

*第三个参数是指向file_operations的指针,

*当用设备号为0创建时,系统一个可以用的设备号创建模块*/

ret=register_chrdev(0,devName,&pStruct);

if(ret<0)

{

printk("registfailure!

\n");

return-1;

}

else

{

printk("thedevicehasbeenregistered!

\n");

device_num=ret;

printk("<1>thevirtualdevice'smajornumber%d.\n",device_num);

printk("<1>Oryoucanseeitbyusing\n");

printk("<1>------more/proc/devices-------\n");

printk("<1>Totalktothedriver,createadevfilewith\n");

printk("<1>------'mknod/dev/myDevicec%d0'-------\n",device_num);

printk("<1>Use\"rmmode\"toremovethemodule\n");

return0;

}

}

/*注销模块,函数名很特殊*/

voidcleanup_module()

{

unregister_chrdev(device_num,devName);

printk("unregisteritsuccess!

\n");

}

staticintmy_open(structinode*inode,structfile*file)

{

if(mutex)

return-EBUSY;

mutex=1;//上锁

printk("<1>maindevice:

%d\n",MAJOR(inode->i_rdev));

printk("<1>slavedevice:

%d\n",MINOR(inode->i_rdev));

printk("<1>%dtimestocallthedevice\n",++counter);

try_module_get(THIS_MODULE);

return0;

}

/*每次使用完后会release*/

staticintmy_release(structinode*inode,structfile*file)

{

printk("Devicereleased!

\n");

module_put(THIS_MODULE);

mutex=0;//开锁

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1