操作系统课程设计.docx
《操作系统课程设计.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计.docx(58页珍藏版)》请在冰豆网上搜索。
操作系统课程设计
课程实验报告
课程名称:
操作系统原理课程设计
专业班级:
学号:
姓名
指导教师:
报告日期:
计算机科学与技术学院
1.实验目的
(1)掌握Linux操作系统的使用方法;
(2)了解Linux系统内核代码结构;
(3)掌握实例操作系统的实现方法。
2.实验环境
本次课程设计采用的操作系统环境是Windows7、Ubuntu双系统,Ubuntu系统版本为15.04,内核版本是Linux3.19。
3.实验内容
3.1实验一
1)编写一个C程序,用fread、fwrite等库函数实现文件拷贝功能。
2)编写一个C程序,使用基于文本的终端图形编程库(curses)或图形界面(QT/GTK),分窗口显示三个并发进程的运行(一个窗口实时显示当前时间,一个窗口实时监测CPU的利用率,一个窗口做1到100的累加求和,刷新周期分别为1秒,2秒和3秒)。
3.2实验二
采用编译内核的方法,添加一个新的系统调用实现文件拷贝功能
编写一个应用程序,测试新加的系统调用
3.3实验三
采用模块方法,添加一个新的字符设备的驱动程序,实现打开/关闭、读/写等基本操作,编写一个应用程序,测试添加的驱动程序。
3.4实验四
1)了解/proc文件的特点和使用方法。
2)监控系统状态,显示系统部件的使用情况。
3)用图形界面监控系统状态,包括CPU和内存利用率、所有进程信息等(可自己补充、添加其他功能)。
4.实验设计
4.1实验一
4.1.1文件拷贝
实现文件拷贝功能需要使用的函数是fopen、fgetc、fputc,由命令行参数获取2个文件名,根据其文件名和路径分别打开该2个文件,设置循环,使用fgetc和fputc函数每次从源文件复制1个字节到目的文件,直到源文件指针到文件尾,实现文件拷贝操作。
4.1.2并发进程分窗口显示
使用图形界面GTK实现窗口的显示,使用fork()创建三个并发进程:
pid=fork():
创建子进程。
返回值:
0从子进程返回
>0从父进程返回
exit进程自我终止,进入僵死状态
wait()等待进程终止(由父进程调用)
exec()执行一个可执行程序(文件)。
4.2实验二
不同的Linux内核版本编译内核和添加系统调用的方法不尽相同,在网上查阅了资料之后找到适合3.19版本内核的编译方法。
所谓系统调用,即Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用,用户可以通过系统调用命令在自己的应用程序中调用它们。
其调用机制为:
使用寄存器中适当的值跳转到内核中事先定义好的代码中执行:
跳转到系统调用的总入口system_call,检查系统调用号,再查找系统调用表sys_call_table,调用内核函数,最后返回。
实验二目的是更改内核中系统调用模块,增加自定义函数实现文件拷贝功能。
4.3实验三
Linux设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程,每个设备文件有两个设备号,主设备号标识驱动程序,从设备号表示使用同一个设备驱动程序的不同硬件设备。
设备驱动程序的功能包括:
对设备初始化和释放,把数据从内核传送到硬件和从硬件读取数据,读取应用程序传给设备文件的数据和回送应用程序请求的数据,检测和处理设备出现的错误。
Linux支持的设备包括三种:
字符设备、块设备和网络设备。
添加设备驱动程序大致需要以下几个步骤:
1.注册设备
2.定义功能函数
3.卸载设备
4.4实验四
proc文件系统特点:
1.进程文件系统和内核文件系统组成的复合体
2.将内核数据对象化为文件形式进行存取的一种内存文件系统
3.监控内核的一种用户接口,拥有一些特殊的纯文本文件,从中可以获取系统状态信息
4.系统信息:
与进程无关,随系统配置的不同而不同
5.进程信息:
系统中正在运行的每一个用户级进程的信息
其中各个文件保存的信息如下:
/proc/cmd/line:
内核启动的命令行
/proc/cpuinfo:
CPU信息
/proc/stat:
CPU的使用情况、磁盘、页面、交换、所有的中断、最后一次的启动时间等
/proc/meminfo:
内存状态的有关信息
利用/proc文件获取系统状态信息,并通过GTK图形化编程将系统信息以及通过这些信息计算得出的如CPU利用率、内存使用等通过窗口显示出来。
5.实验步骤
5.1实验一
5.1.1文件拷贝
文件拷贝主要是利用文件指针操作,在源文件和目的文件之间进行字符的复制,拷贝之前要判断源文件是否存在以及能否打开,这需要设置一个判断语句,同时也要设置判断语句判断目的文件是否存在,若不存在需要能够创建一个目的文件,最后执行循环拷贝。
步骤如下:
1.在Linux终端使用编译命令:
gccmycopy.c-omycopy产生可执行文件。
2.创建源文件wangzihao目的文件shaochongjun。
3.编辑源文件:
4.打开可执行程序:
./mycopywangzihaoshaochongjun
5.查看目的文件发现已经实现拷贝:
6.若源文件不存在会报错:
5.1.2并发进程分窗口显示
1.使用fork()函数创建三个进程,使用exec函数族实现程序的调用:
2.调用创建窗口函数init_window(),将进程中的信息在窗口中显示:
3.分别创建三个程序实现显示系统时间、CPU利用率、累加求和功能:
4.运行结果如下:
5.2实验二
原内核版本:
3.19.0
编译新内核版本:
3.19.8
1.下载内核并解压
2.系统调用函数实现:
修改kernel/sys.c文件,在文件的最后添加新的系统调用函数:
sys_mycall(char*sourceFile,char*destFile)
3.设置系统调用号:
修改arch/x86/syscalls/syscall_32.tbl,在最后一行添加新的系统调用号
4.添加系统调用声明到头文件 :
~$viinclude/asm-generic/syscalls.h
在#endif前添
#ifndefsys_mycall
asmlinkage long sys_mycall(long number);
#endif
5.安装基本编译套件:
apt-getinstallbuild-essentialkernal-packagelibncurses5-devfakeroot
6.配置内核:
makemenuconfig
7.编译内核:
make-j4
8.安装内核:
makemodules_install
makeinstall
9.重启进入新的内核
10.编写测试程序测试新的系统调用:
测试结果如下:
5.3实验三
1.编写Makefile文件:
2.编写设备功能函数:
(见程序清单)
3.设备加载:
makeclean
make
加载模块:
insmodwzhdriver.ko
输入cat/proc/devices得设备驱动的主设备号为:
加载设备,分配设备号:
mknod/dev/wzhdriverc2480
更改操作权限:
chmod666/dev/wzhdriver
4.运行测试程序,结果:
5.4实验四
1系统信息页:
2进程信息页:
3内存资源页:
6.调试记录
1.在编译gtk程序时,需要添加`pkg-config--cflags--libsgtk+-3.0`.参数。
2.实验一程序过于简单,健壮性不大。
3.由于一开始没有加入刷新函数,导致实验一显示窗口数据不变化,在同学帮助下改正。
4.编译内核占用大量时间后来发现在make后添加-j4可以大大提升速度。
5.
7.心得体会
本次课程设计主要目的是熟悉Linux系统,掌握Linux操作系统的使用方法,了解Linux系统内核代码结构,掌握实例操作系统的实现方法。
由于刚开始接触Linux,实验的开始遇到了不少困难,GTK的安装和使用花费了我不少时间,并行程序是操作系统课程学过的内容,主要难点是图形化界面的设计。
实验二是耗费时间最多的,由于每个版本的内核编译方式不同,耗费了大量时间查找编译内核的方法,同时编译一次内核需要一个小时以上,不过皇天不负有心人最后我成功添加了系统调用。
添加设备驱动比较简单,主要是了解了Linux设备驱动的原理,熟悉设备驱动的安装过程。
分析/proc文件主要是搭建图形化界面,在借鉴了网上资源设计的窗口之后,我设计了简单的监控系统图形界面,其中CPU利用率以及占用曲线等需要计算。
通过本次实验我学到了很多东西,熟悉了Linux系统的使用方法,对Linux系统内核代码结构有了大致的了解,掌握了图形化界面GTK的使用,总而言之本次试验我获益匪浅。
8.程序清单
8.1实验一
8.1.1文件拷贝
#include
intmain(intargc,char*argv[])
{
if(argc!
=3)
{
printf("Errorinargc!
\n");
return0;
}
FILE*fsource=NULL;
FILE*ftarget=NULL;
if((fsource=fopen(argv[1],"rb"))==NULL)
{
printf("Failtoopensourcefile!
\n");
return0;
}
if((ftarget=fopen(argv[2],"wb"))==NULL)
{
printf("Failtoopentargetfile!
\n");
return0;
}
intc;
while((c=fgetc(fsource))!
=EOF)
{
fputc(c,ftarget);
}
fclose(fsource);
fclose(ftarget);
return0;
}
8.1.2并发进程窗口显示
主函数:
#include
#include
#include
intmain()
{
pid_ttime;
pid_tcpu;
pid_tsum;
if((time=fork())==-1)
{
printf("forkerror\n");
return-1;
}
if(time==0)
{
execlp("./time",0);
}else
{
if((cpu=fork())==-1)//createcpu
{
printf("forkerror\n");
return-1;
}
if(cpu==0)
{
execlp("./cpu",0);
}else
{
if((sum=fork())==-1)//createsum
{
printf("forkerror\n");
return-1;
}
if(sum==0)
{
execlp("./sum",0);
}else//fatherprocess
{
wait(&time);
wait(&cpu);
wait(&sum);
}
}
}
}
系统时间:
#include
#include
#include
#include
chart[50];
GtkWidget*label;
gettime(){
time_ttimep;
time(&timep);
sprintf(t,"%s",ctime(&timep));}
void*thread(void*argc){
while
(1){
gettime();
gtk_label_set_text(GTK_LABEL(label),t);
sleep
(1);}
}
intmain(intargc,char*argv[])
{pthread_tid;
inti,ret;
ret=pthread_create(&id,NULL,(void*)thread,NULL);
GtkWidget*vbox;//定义一个组装盒;
GtkWidget*window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc,&argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"time");
gtk_window_set_default_size(GTK_WINDOW(window),300,200);
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
label=gtk_label_new(t);
gtk_container_add(GTK_CONTAINER(window),label);
gtk_widget_show(label);
/*开始显示窗口*/
gtk_widget_show(window);
gtk_main();
return0;
}
CPU利用率:
#include
#include
#include
GtkWidget*label;//theuserateofcpu
charc[5];
floatcpu();
void*thread(void*arg)
{
floatusage;
while
(1)
{
sleep
(2);
usage=cpu();
sprintf(c,"theusageofcpuis%f%%",usage);
gtk_label_set_text(GTK_LABEL(label),c);
}
}
floatcpu()
{
FILE*fp;
charbuf[128];
charcpu[5];
longintuser,nice,sys,idle,iowait,irq,softirq;
longintall1,all2,idle1,idle2;
floatusage;
fp=fopen("/proc/stat","r");
if(fp==NULL)
printf("error\n");
fgets(buf,sizeof(buf),fp);
sscanf(buf,"%s%ld%ld%ld%ld%ld%ld%ld",cpu,&user,&nice,&sys,&idle,&iowait,&irq,&softirq);
all1=user+nice+sys+idle+iowait+irq+softirq;
idle1=idle;
rewind(fp);
//second
sleep
(1);
memset(buf,0,sizeof(buf));
cpu[0]='\0';
user=nice=sys=idle=iowait=irq=softirq=0;
fgets(buf,sizeof(buf),fp);
sscanf(buf,"%s%ld%ld%ld%ld%ld%ld%ld",cpu,&user,&nice,&sys,&idle,&iowait,&irq,&softirq);
all2=user+nice+sys+idle+iowait+irq+softirq;
idle2=idle;
usage=(float)(all2-all1-(idle2-idle1))/(all2-all1)*100;
returnusage;
}
intmain(intargc,char*argv[])
{pthread_tid;
inti,ret;
ret=pthread_create(&id,NULL,(void*)thread,NULL);
GtkWidget*window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc,&argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"cpu");
gtk_window_set_default_size(GTK_WINDOW(window),300,200);
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
label=gtk_label_new(c);
gtk_container_add(GTK_CONTAINER(window),label);
gtk_widget_show(label);
/*开始显示窗口*/
gtk_widget_show(window);
gtk_main();
return0;
}
求和:
#include
#include
#include
#include
chars[1000];
GtkWidget*label;
void*thread(void*argc){
inti,j,sum;
for(i=1,sum=0,j=1;i<=100;i++){
sleep(3);
sum=sum+j;
j+=1;
sprintf(s,"%d",sum);
gtk_label_set_text(GTK_LABEL(label),s);
}
}
intmain(intargc,char*argv[])
{pthread_tid;
inti,ret;
ret=pthread_create(&id,NULL,(void*)thread,NULL);
GtkWidget*vbox;//定义一个组装盒;
GtkWidget*window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc,&argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"sum");
gtk_window_set_default_size(GTK_WINDOW(window),300,200);
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
label=gtk_label_new(s);
gtk_container_add(GTK_CONTAINER(window),label);
gtk_widget_show(label);
/*开始显示窗口*/
gtk_widget_show(window);
gtk_main();
return0;
}
8.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);
return10;}
测试程序:
#include
#include
#include
intmain(intargc,char**argv)
{
inti=syscall(359,argv[1],argv[2]);
printf("the%d",i);
return1;
}
8.3实验三
设备驱动:
#include
#include
#include
#include
MODULE_LICENSE("GEL");
MODULE_AUTHOR("wangzihao");
#defineDEV_NAME"wzhdriver"
staticssize_tGlobalRead(structfile*,char*,size_t,loff_t*);
staticssize_tGlobalWrite(structfile*,constchar*,size_t,loff_t*);
staticintchar_major=0;
staticintGlobalDat