华科操作系统课设报告.docx
- 文档编号:10926223
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:17
- 大小:323.34KB
华科操作系统课设报告.docx
《华科操作系统课设报告.docx》由会员分享,可在线阅读,更多相关《华科操作系统课设报告.docx(17页珍藏版)》请在冰豆网上搜索。
华科操作系统课设报告
华科操作系统课设报告
华中科技大学
操作系统课程设计实验报告
专业:
计算机科学与技术
班级:
1101
姓名:
许阳
学号:
U201014241
一、实验目的
掌握Linux操作系统的使用方法;
了解Linux系统内核代码结构;
掌握实例操作系统的实现方法。
二、实验要求
1、掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。
●编一个C程序,其内容为实现文件拷贝的功能;
●编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。
要求用到Linux下的图形库。
2、掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。
另编写一个应用程序,调用新增加的系统调用。
实现的功能是:
文件拷贝;
3、掌握增加设备驱动程序的方法。
通过模块方法,增加一个新的设备驱动程序,其功能可以简单。
实现字符设备的驱动;
4、了解和掌握/proc文件系统的特点和使用方法
●了解/proc文件的特点和使用方法
●监控系统状态,显示系统中若干部件使用情况
●用图形界面实现系统监控状态。
5、设计并实现一个模拟的文件系统(选作)
三、实验一
1、编一个C程序,其内容为实现文件拷贝的功能
要实现文件拷贝功能,主要用到的函数是open、write、read。
以前在windows下写C语言打开文件常用的fopen,此时不能用,因为fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api;所以应该直接使用linux中的系统函数open。
主要用到的头文件:
Unistd.h\\包含了许多Linux系统服务的函数原型,如:
read、write
Fcntl.h\\定义了很多宏和open,fcntl函数原型
Stdio.h\\标准输入输出头文件
sys/types.h\\此头文件包含适当时应使用的多个基本派生类型
sys/stat.h\\包含了获取文件属性的一些函数
errno.h\\用于调试错误代码是所需要的一些errno变量
string.h\\包含了处理字符串的一些函数
设计思路:
由命令行参数获取2个文件名,根据其文件名和路径分别打开该2个文件,设置一个循环,从源文件复制N个字节到目的文件,直到源文件指针到文件尾,最后关闭2个文件。
在可能出错的地方需要加上相应的报错代码和中断,并输出错误信息,以方便调试或是往后应用在第2小题中可能发生的错误。
理清楚设计思路后,根据需求写出相应的源代码见后页源程序代码scopy.c;在Linux终端使用编译命令gcc–oscopyscopy.c将程序编译并生产exe可执行文件。
然后手动创建一个测试文件test.txt,在终端输入命令
./scopytest.txttarget.txt
这样就能将源文件test.txt复制到目标文件target.txt
程序源代码scopy.c:
#include
#include
#include
#include
#include
#include
#include
#defineBUFFER_SIZE1024//缓冲区大小
intmain(intargc,char**argv)
{
intfrom_fd,to_fd;
intbytes_read,bytes_write;
charbuffer[BUFFER_SIZE];//设定一个缓冲区
char*ptr;
if(argc!
=3)//三个参数
{
fprintf(stderr,"Usage:
%sfromfiletofile\n\a",argv[0]);
return(-1);
}
/*打开源文件*/
if((from_fd=open(argv[1],O_RDONLY))==-1)
{
fprintf(stderr,"Open%sError:
%s\n",argv[1],strerror(errno));
return(-1);
}
/*创建目的文件*/
if((to_fd=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1)
{
fprintf(stderr,"Open%sError:
%s\n",argv[2],strerror(errno));
return(-1);
}
while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
{
/*出错*/
if((bytes_read==-1)&&(errno!
=EINTR))break;
elseif(bytes_read>0)
{
ptr=buffer;
while(bytes_write=write(to_fd,ptr,bytes_read))
{
/*出错*/
if((bytes_write==-1)&&(errno!
=EINTR))break;
/*写完了所有读的字节*/
elseif(bytes_write==bytes_read)break;
/*只写了一部分,继续写*/
elseif(bytes_write>0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
/*写的时候出错*/
if(bytes_write==-1)break;
}
}
close(from_fd);
close(to_fd);
return
(1);
}
2、编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。
要求用到Linux下的图形库。
安装Linux下的GTK+:
首先要在Linux下载GTK+相关库文件并安装。
在终端输入sudoapt-getinstallgnome-core-devel,然后根据提示操作,就会安装libgtk2.0-devlibglib2.0-dev等开发所需的相关库文件。
$sudoapt-getinstallbuild-essential
$sudoapt-getinstallgnome-core-devel
$sudoapt-getinstallpkg-config
$sudoapt-getinstalllibgtk2.0*
编译GTK+代码时需要包含的头文件是gtk/gtk.h,此外,还必须连接若干库;比如编译test.c时用以下命令。
gcc–otesttest.c`pkg-config--cflags--libsgtk+-2.0`
在编写代码时需要用到的控件、窗口等视窗物件形态,用类GtkWidget定义其为指针类型。
编写一个GTK+程序的基本步骤如下:
●初始化Gtk
●建立控件
●登记消息与消息处理函数
●执行消息循环函数gtk_main()
之后所设计的3个进程,基本上都是以这样的方式编写代码的,因为之前曾用过OpenGL,所以在这方面掌握的比较快。
初始化主要使用的函数有
gtk_init(&argc,&argv);//启动GTK
gtk_window_new(GTK_WINDOW_TOPLEVEL);//创建窗口
gtk_window_set_title(GTK_WINDOW(window),"标题名");//设置窗口标题名
gtk_widget_set_usize(window,200,200);//设置窗口大小
gtk_widget_show(window);//显示窗口
建立控件的一般流程
/*创建表格准备封装*/
gtk_table_new(//创建多少列
gintrows,//创建多少栏
gintcolumns,//用来决定表格如何来定大小
ginthomogeneous);
/*这个函数是将表格table,结合到窗口window里*/
gtk_container_add(GTK_CONTAINER(window),table);
gtk_widget_show(table);//显示该表格
/*要把物件放进box中,可用以下函数*/
voidgtk_table_attach_defaults(
GtkTable*table,//参数("table")是选定某表格
GtkWidget*widget,//("child")是想放进去的物件
gintleft_attach,//以下参数是指定把物件放在哪里,及用多少个boxes
gintright_attach,
ginttop_attach,
gintbottom_attach);
实验截图:
实验源代码:
process.c:
#include
#include
#include
gintprogress_timeout(gpointerpbar)
{
gdoublenew_val;
chars[10];
new_val=gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(pbar))+0.01;
if(new_val>1.0)
new_val=0.0;
sprintf(s,"%.0f%%",new_val*100);
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pbar),new_val);
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pbar),s);
returnTRUE;
}
voiddestroy_progress(GtkWidget*widget)
{
gtk_main_quit();
}
voidshow(intargc,char*argv[],char*title)
{
GtkWidget*window;
GtkWidget*vbox;
GtkWidget*pbar;
GtkWidget*pbar2;
GtkWidget*button;
GtkWidget*label;
inttimer;
charid_char[50];
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable(GTK_WINDOW(window),TRUE);
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy_progress),NULL);
gtk_window_set_title(GTK_WINDOW(window),title);
gtk_container_set_border_width(GTK_CONTAINER(window),0);
vbox=gtk_vbox_new(FALSE,10);
gtk_container_set_border_width(GTK_CONTAINER(vbox),10);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show(vbox);
sprintf(id_char,"本进程ID:
%d",getpid());
label=gtk_label_new(id_char);
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);
gtk_widget_show(label);
sprintf(id_char,"父进程ID:
%d",getppid());
label=gtk_label_new(id_char);
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);
gtk_widget_show(label);
pbar=gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(vbox),pbar,FALSE,FALSE,0);
gtk_widget_show(pbar);
timer=gtk_timeout_add(100,progress_timeout,pbar);
button=gtk_button_new_with_label("close");
g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),window);
gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,0);
GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
gtk_widget_grab_default(button);
gtk_widget_show(button);
gtk_widget_show(window);
gtk_main();
}
intmain(intargc,char*argv[])
{
intpid=fork();
if(pid<0)
printf("error!
\n");
elseif(pid==0)
{
intpid=fork();
if(pid<0)
printf("error!
\n");
elseif(pid==0)
show(argc,argv,"process3");
else
show(argc,argv,"process2");}
else
show(argc,argv,"process1");
}
四、实验二
Linux内核,简单来说就是一套用来控制计算机最底层的硬件设备,如处理器、内存、硬盘等的一种软件,一般称为操作系统,在Linux术语中称为内核。
其中包含的模块有存储管理、CPU和进程管理、文件系统、设备管理和驱动、网络通信,以及系统的初始化(引导)、系统调用等。
这次题目就是要更改Linux内核中的”系统调用”模块,在其中添加自定义的函数,实现功能是文件拷贝。
工作流程基本如下:
下载并解压内核
修改内核中关于系统调用所需要的文件
编译内核
安装内核
测试功能
1.下载并解压内核
到官方网站http:
//www.kernel.org/下载内核linux-2.6.37.4,打开终端,使用下列命令对其解压到目录/usr/src:
sudotar-xjvflinux-2.6.37.4.tar.bz2-C/usr/src
该目录用来存放内核的源码。
2.修改内核
首先要对系统调用模块的源码添加一个自定义函数,即对/usr/src/linux-2.6.37.4/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);
return10;
}
修改完函数之后,接下来要修改系统调用号所对应的函数名,即修改/usr/src/linux-2.6.32.10/arch/x86/include/asm/unistd_32.h
该文件定义了系统调用号,我们只要找一没被使用的系统调用号,用该号给我们自定义函数使用,比如
#define__NR_sys_mycall337
/*定义系统调用sys_mycall的系统调用号为337*/
修改完系统调用号后,接下来要修改系统调用表,即/usr/src/linux-2.6.32.10/arch/x86/kernel/syscall_table_32.S,这个文件是用汇编语言编写的,因此要让自定义的系统调用相对于其他系统调用的顺序337个,写上.longsys_mycall/*337*/
基本修改完以上源码后,接下来对其进行默认的净化、设置等。
使用下列代码对其源码进行处理
sudomakemrproper净化解压后的源代码
sudomakemenuconfig对内核选项进行配置
如果这一步有错误可能是正在使用的系统没有安装必要的库文件,如ncurses、libncurses*,这时候需要输入如下指令来安装
首先回到系统根目录
sudoapt-getinstallncurses
sudoapt-getinstalllibncurses*
依照提示就能安装好必要的库文件了。
然后再回到内核源码的目录下尝试使用sudomakemenuconfig对内核选项进行配置。
sudomakedep建立模块间的依赖信息
sudomakeclean删除配置时留下的一些不用的文件
3.编译内核
接下来是最费时间的环节,少则2个小时,多则3个小时的编译,需要再三确保前面步骤是否正确后再进行下一步。
sudomakebzImage编译内核
这个过程大概是20多分钟
sudomakemodules编译内核模块
这个过程大概要100分钟~150分钟左右,一般如果有错误,会在前十几分钟就停止编译并报错。
4.安装内核
比较简单,只需要两条指令
sudomakemodules_install安装内核模块
sudomakeinstall安装内核
安装完毕后,需要开机时选择使用新的Linux核心,要做下列修改:
1)复制内核到系统启动引导目录
cp/usr/src/linux-2.6.37.4/arch/i386/boot/bzImage/boot/vmlinuz-2.6.37.4-mykernel
2)创建初始RAM磁盘——initrd
在创建之前先安装必要的程序
apt-getinstallbootcd-mkinitramfs
mkinitramfs-o/boot/initrd.img-2.6.37.4
3)更新grub
在/boot/grub/grub.cfg中,复制一段旧的核心代码,并将里面linux和initrd中的路径改为新增的,注意不能用update-grub2
在/boot中复制一个旧的config-xxxxxx做为自己的
4)cd/boot
cpinitrd.img-2.6.37.4initrd-2.6.37.4.old
以上是备份initrid,下面是修改
depmod–a
update-initramfs-k2.6.37.4–c
cd/tmp
gzip-dc/boot/initrd.img-2.6.37.4|cpio-id
touchlib/modules/2.6.37.4/modules.dep
find./|cpio-Hnewc-o>/boot/initrd.img-2.6.37.4.new
gzip/boot/initrd.img-2.6.37.4.new
cd/boot
mvinitrd.img-2.6.37.4.new.gzinitrd.img-2.6.37.4
5)重开机测试
5.测试功能
用C语言编写测试程序testsys.c,源代码如下:
#include
#include
#include
intmain(intargc,char**argv)
{
inti=syscall(349,argv[1],argv[2]);/*337为系统调用号*/
printf("successfully!
\r\n");
printf("%d",i);
return1;
}
编译gcc–otestsystestsys.c
运行./testsystest.txttarget.txt
系统调用337号功能,拷贝文件test.txt到target.txt
运行结果截图如下:
.
【实验心得】
由于上学期操作系统学习的并不太好,所以这学期做课设还是遇到了很大的困难,制作出了前二步,最终还是靠着网上的一些代码才实现了完整的功能,不过从看、这次课程设计中,我还是学到了很有用的知识,比如linux内核的编译,GTK的使用等等,也请教了许多同学也和他们一起探讨过,从中受益匪浅。
最后也谢谢老师对我一学期以来的指导!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)