华科操作系统实验报告DOCWord格式.docx
- 文档编号:17268655
- 上传时间:2022-11-30
- 格式:DOCX
- 页数:17
- 大小:57.93KB
华科操作系统实验报告DOCWord格式.docx
《华科操作系统实验报告DOCWord格式.docx》由会员分享,可在线阅读,更多相关《华科操作系统实验报告DOCWord格式.docx(17页珍藏版)》请在冰豆网上搜索。
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操作系统的使用方法,包括键盘命令、系统调用;
1)编一个C程序,其内容为实现文件拷贝的功能。
1 任务分析:
在Linux下,如果要编译一个C语言源程序,要使用到gcc编译器。
gcc编译器中,-o选项表示我们要求输出的可执行文件名。
-c选项表示我们只要求编译器输出目标代码,而不必要输出可执行文件。
-g选项表示我们要求编译器在编译的时候提供我们以后对程序进行调试的信息。
知道了这三个选项,我们就可以编译我们自己所写的简单的源程序了。
文件拷贝的C程序主要用到如下几个函数:
●open:
打开文件
open()函数
功能描述:
用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。
所需头文件:
#include<
sys/types.h>
#include<
sys/stat.h>
fcntl.h>
函数原型:
intopen(constchar*pathname,intflags,intperms)
参数:
pathname:
被打开的文件名(可包括路径名如"
dev/ttyS0"
)
flags:
文件打开方式,
O_RDONLY:
以只读方式打开文件
O_WRONLY:
以只写方式打开文件
O_RDWR:
以读写方式打开文件
O_CREAT:
如果改文件不存在,就创建一个新的文件,并用第三个参数为其设置权限
返回值:
成功:
返回文件描述符
失败:
返回-1
●close:
关闭文件
close()函数
用于关闭一个被打开的的文件
#include<
unistd.h>
函数原型:
intclose(intfd)
fd文件描述符
函数返回值:
0成功,-1出错
●read:
读操作
read()函数
从文件读取数据。
ssize_tread(intfd,void*buf,size_tcount);
fd:
将要读取数据的文件描述词。
buf:
指缓冲区,即读取的数据会被放到这个缓冲区中去。
count:
表示调用一次read操作,应该读多少数量的字符。
返回值:
返回所读取的字节数;
0(读到EOF);
-1(出错)。
●write:
写操作
write()函数
向文件写入数据。
ssize_twrite(intfd,void*buf,size_tcount);
写入文件的字节数(成功);
-1(出错)
2 实现文件拷贝的源程序如下所示:
#include<
stdio.h>
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)
{
TARGETFILEOPENFAIL!
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程序,其内容为分窗口同时显示三个并发进程的运行结果。
程序是指令的有序集合,是一个静态概念,其本身并没有任何运行的含义。
而进程是程序在处理机上的一次执行过程,是一个动态概念。
一个程序可能有许多进程,而每一个进程又可以有许多子进程。
为了区分各个不同的进程,系统给每一个进程分配了一个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文件:
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)
/home/hukeled/1.2/3"
returna.exec();
2、掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。
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>
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;
测试程序源代码
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)安装内核
(12)重启选用新内核
第二步:
添加自定义系统调用
(1)添加系统调用函数,修改文件:
/kernel/sys.c
do{
(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;
3、掌握增加设备驱动程序的方法。
linxu系统中,在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。
设备驱动程序是内核的一部分,它完成以下的功能:
1.对设备初始化和释放.
2.把数据从内核传送到硬件和从硬件读取数据.
3.读取应用程序传送给设备文件的数据和回送应用程序请求的数据.
4.检测和处理设备出现的错误.
Linux操作系统允许设备驱动程序作为可装载内核模块实现,这也就是说,设备的接口实现不仅可以在Linux操作系统启动时进行注册,而且还可以在Linux操作系统启动后装载模块时进行注册。
总之,Linux操作系统支持多种设备。
2 设备驱动程序代码:
#include"
linux/kernel.h"
linux/module.h"
linux/fs.h"
linux/init.h"
linux/types.h"
linux/errno.h"
linux/uaccess.h"
linux/kdev_t.h"
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!
thedevicehasbeenregistered!
device_num=ret;
<
1>
thevirtualdevice'
smajornumber%d.\n"
device_num);
Oryoucanseeitbyusing\n"
------more/proc/devices-------\n"
Totalktothedriver,createadevfilewith\n"
------'
mknod/dev/myDevicec%d0'
-------\n"
Use\"
rmmode\"
toremovethemodule\n"
/*注销模块,函数名很特殊*/
voidcleanup_module()
unregister_chrdev(device_num,devName);
unregisteritsuccess!
staticintmy_open(structinode*inode,structfile*file)
if(mutex)
return-EBUSY;
mutex=1;
//上锁
maindevice:
%d\n"
MAJOR(inode->
i_rdev));
slavedevice:
MINOR(inode->
%dtimestocallthedevice\n"
++counter);
try_module_get(THIS_MODULE);
/*每次使用完后会release*/
staticintmy_release(structinode*inode,structfile*file)
Devicereleased!
module_put(THIS_MODU
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 实验 报告 DOC