华中科技大学计算机学院操作系统课程设计报告1.docx

上传人:b****3 文档编号:13266849 上传时间:2023-06-12 格式:DOCX 页数:31 大小:1.05MB
下载 相关 举报
华中科技大学计算机学院操作系统课程设计报告1.docx_第1页
第1页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第2页
第2页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第3页
第3页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第4页
第4页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第5页
第5页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第6页
第6页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第7页
第7页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第8页
第8页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第9页
第9页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第10页
第10页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第11页
第11页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第12页
第12页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第13页
第13页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第14页
第14页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第15页
第15页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第16页
第16页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第17页
第17页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第18页
第18页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第19页
第19页 / 共31页
华中科技大学计算机学院操作系统课程设计报告1.docx_第20页
第20页 / 共31页
亲,该文档总共31页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

华中科技大学计算机学院操作系统课程设计报告1.docx

《华中科技大学计算机学院操作系统课程设计报告1.docx》由会员分享,可在线阅读,更多相关《华中科技大学计算机学院操作系统课程设计报告1.docx(31页珍藏版)》请在冰点文库上搜索。

华中科技大学计算机学院操作系统课程设计报告1.docx

华中科技大学计算机学院操作系统课程设计报告1

华中科技大学

嵌入式操作系统课程设计实验报告

 

院系:

计算机科学与技术学院

专业:

班级:

姓名:

指导老师:

报告时间:

 

计算机科学与技术学院

1.课程设计目的…………………………………………………………3

2.课程设计环境搭建……………………………………………………3

3.内容一:

熟悉和理解Linux编程环境

3.1内容要求……………………………………………………………………5

3.2设计过程及实现……………………………………………………………5

4.内容二:

掌握添加系统调用的方法

4.1内容要求……………………………………………………………………9

4.2设计过程及实现……………………………………………………………9

5.内容三:

掌握添加设备驱动程序的方法

5.1内容要求…………………………………………………………………17

5.2设计过程及实现…………………………………………………………17

6.内容四:

理解和分析/proc文件

6.1内容要求…………………………………………………………………22

6.2设计过程及实现…………………………………………………………22

1课程设计目的

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

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

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

2课程设计环境搭建

(1)windows7上,利用虚拟机软件VMware软件搭建的linux平台:

◎Ubuntu11.10(安装包:

ubuntu-11.10-desktop-i386)

◎内核:

linux-headers-3.0.0-12-generic

(2)更改root登录:

在现阶段Ubuntu的系统中,是不允许直接以root身份登录系统的,但是在做课设的过程中,需要大量的使用root权限来进行命令的操作。

如果以普通用户登录ubuntu,会连编辑一个文件都非常周折。

为此,我找到了一种修改系统文件,以达到直接使用root身份登录的方法:

◎开始的时候,只能以普通用户登录,用Ctrl+Alt+T打开终端:

初始化/修改root密码

sudopasswdroot

用vi编辑器修改这个文件:

sudovi/etc/lightdm/lightdm.conf

在文件最后加入这么一行代码:

greeter-show-manual-login=true

然后保存退出,sudoreboot重启系统。

之后就可以输入root用户登录。

(3)在添加系统调用中用到的其他内核包:

◎下载和当前实验环境最为接近的系统版本(这点很重要)

使用apt-getinstalllinux-source-3.0.0命令,

◎下载结果是linux-source-3.0.0.tar.bz2

◎解压命令:

tar–xjvflinux-source-3.0.0.tar.bz2–C/usr/src

◎解压后,在/usr/src目录下得到内核文件夹linux-source-3.0.0

(4)在调用linux图形库时需要安装GTK环境:

◎安装gcc/g++/gdb/make等基本编程工具

apt-getinstallbuild-essential

Tip:

如果提示由于依赖项不能安装,需要使用apt的强化版aptitude,这个工具可以自动分析软件包依赖,系统一般不自带,需要先安装,具体过程是:

apt-getinstallaptitude

aptitudeinstallbuild-essential

aptitude这个工具很强大,对于解决软件包安装时的依赖问题很有帮助。

◎安装libgtk2.0-devlibglib2.0-dev等开发相关的库文件:

apt-getinstallgnome-core-devel

◎安装GTK核心组件:

apt-getinstalllibgtk2.0-dev

这个安装完成后,GTK环境就基本搭建成功,网上有些教程说要安装其他配置文件,经我亲测,发现只要安装libgtk2.0-dev这个包就能搞定。

3内容一:

熟悉和理解Linux编程环境

3.1内容要求

(1)编写一个C程序,实现文件拷贝功能

(2)编写一个C程序,使用Linux下的图形库,分窗口显示三个并发进程运行;

3.2设计过程及实现

(1)文件拷贝:

①文件的拷贝主要的思想就是利用文件指针操作,在两个文件之间进行按字符的fget和fput。

从而完成整个文件的拷贝操作。

在这个基本功能之外,需要增加程序的健壮性,具体有以下几个方面:

·源文件是否存在且能读取数据;

·是否能创建目的文件,且能向里面写入数据;

·程序需要的argc参数个数是否满足要求;

②基于以上几点和内容要求,主要的程序段如下:

if(argc!

=3)//判断参数个数是否为3,否则返回

{

printf("Errorinargc!

\n");

return0;

}

if((fsource=fopen(argv[1],"rb"))==NULL)

{

printf("Errorinopensourcefile!

\n");//判断源文件是否能打开和读出

return0;

}

if((ftarget=fopen(argv[2],"wb"))==NULL)

{

printf("Errorinopentargetfile!

\n");//判断目的文件时候能创建和写入

return0;

}

while((c=fgetc(fsource))!

=EOF)

{

fputc(c,ftarget);//按字符读取和写入数据

}

 

③执行结果如下:

将source/source.txt文件拷贝到到target.txt,开始时如下图3-1所示:

图3-1复制开始前source/source.txt文件内容

利用mycopy程序复制,查看target.txt文件复制结果如下图3-2所示:

图3-2复制后target.txt文件的具体内容

(2)实现三个进程之间的并发程序:

这里需要用到课程实验时的fork()程序以及GTK的图形显示。

①基本fork()程序,调用显示一个父进程和两个子进程的结构如下:

if((pid_1=fork())==0)

{

printf("Child1#isrunning......\n");//第一个子进程Child1#

show(argc,argv,"ThisisChild1#");//调用函数显示窗口

}

else

{

if((pid_2=fork())==0){

printf("Child2#isrunning......\n");//第二个子进程Child2#

show(argc,argv,"ThisisChild2#");//调用函数显示窗口

}

else{

printf("Parent#isrunning......\n");//父进程Parent#

//由于父进程需要显示全部子进程PID,所以这里直接用参数画窗口

}

}

 

②调用GTK显示窗体函数模块的结构:

voidshow(intargc,char*argv[],char*title){

gtk_init(&argc,&argv);//初始化工具包并且获取命令行参数;

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);//创建新的窗口;

//设定窗口的位置;

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);

//监听窗口的destroy事件;

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),20);//设定宽度;

//使用gtk_vbox_new函数建立纵向组装盒;

//为了显示构件,必须将构件放入组装盒中,并将组装盒放在窗口内;

vbox=gtk_vbox_new(FALSE,10);

gtk_container_set_border_width(GTK_CONTAINER(vbox),100);//设定宽度;

gtk_container_add(GTK_CONTAINER(window),vbox);

gtk_widget_show(vbox);

//使用gtk_box_pack_start函数将构件放到组装盒中;

sprintf(id_char,"%s,MyID:

%d",title,getpid());//显示PID号

label=gtk_label_new(id_char);

gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,10);

gtk_widget_show(label);

sprintf(id_char,"父进程ID:

%d",getppid());//显示PPID号

label=gtk_label_new(id_char);

gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,10);

gtk_widget_show(label);

button=gtk_button_new_with_label("close");//关闭窗口按钮

//信号登记函数,监听按钮的clicked事件。

//当窗口clicked时,gtk_widget_destroy就会被调用。

//而gtk_widget_destroy函数又调用gtk_main_quit()结束程序运行。

g_signal_connect_s(G_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),window);

gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,10);

GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);

gtk_widget_grab_default(button);

//函数显示窗口中的组件

gtk_widget_show(button);

gtk_widget_show(window);

//准备将窗口和所有的组件显示在屏幕上,函数必须在GTK程序的最后调用.

gtk_main();

}

③编译代码forkgtk.c,运行;

编译命令为:

gcc-oforkgtkforkgtk.c`pkg-config--cflags--libsgtk+-2.0`

程序运行结果如下图3-3所示:

图3-3三个并行显示窗口

4.内容二:

掌握添加系统调用的方法

4.1内容要求

(1)采用编译内核的方法,添加一个新的系统调用。

(2)编写一个应用程序,测试新添加的系统调用。

(3)系统调用的功能:

文件拷贝。

4.2设计过程及实现

在这一个部分,投入了比较多的时间。

总结起来,主要有这么几个方面:

·linux内核版本的不同,linux2.X和linux3.X直接添加系统调用和重新编译内核的方法有差异,甚至linux2.X之间,内核文件也有变化。

·再加上相关资料的步骤和方法不尽相同,甚至还有互斥的步骤,这就使得这个推进比较漫长。

我之前的Ubuntu版本是13.04,后来发现因为是64位的,行不通,只好换了一个低版本的Ubuntu11.10,经过自己的实际工作,下面是在运行成功之后,总结的一个过程。

(环境和内核配置见本报告第二部分)

(1)修改Makefile文件,修改系统版本后缀:

如下图4-1所示:

这里加的是本人的姓名的首字母,以示区分。

图4-1修改Makefile文件版本

(2)修改/usr/src/linux-source-3.0.0/kernel/目录下的sys.c文件,在最后加入新的系统调用,拷贝函数实现。

如下所示:

asmlinkageintsys_zcycopychar*s_file,constchar*t_file)

{

constintBUF_SIZE=512;

intfin,fout;

charbuf[BUF_SIZE];

intcopy_count;

mm_segment_tfs;//段操作的初始化

fs=get_fs();

set_fs(get_ds());

/*系统调用打开源文件,若失败,返回-1*/

if((fin=sys_open(s_))==-1)

{

return-1;

printk("Errorinoensourcefile!

");

}

/*系统调用创建并打开目标文件,若失败,返回-2*/

if((fout=sys_open(t_|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)

{

return-2;

printk("Errodinopentargetfile!

");

}

while(copy_count=sys_read(fin,buf,BUF_SIZE))

{/*拷贝文件,若失败,返回-3*/

if(copy_count==-1||sys_write(fout,buf,copy_count)==-1)

{

return-3;

printk("Errorincopyfile!

");

}

}

set_fs(fs);/*段操作结束*/

return0;

}

(3)修改/usr/src/linux-source-3.0.0/arch/x86/include/asm/文件夹下面头文件:

unistd_32.h,在文件的系统调用号部分添加一个新的系统调用,具体添加行如下:

#define__NR_sys_zcycopy

同时把下面的总调用号加1,变成348。

具体截图如下图4-2所示。

图4-2添加系统调用号

(4)修改/usr/src/linux-source-3.0.0/x86/kernel/syscall_table_32.s,①加入新的一行:

.longsys_zcycopyfile/*347*/

②具体实现如下图4-3所示:

图4-3填写系统调用入口表

③当用户程序需要系统提供服务的时候,比如347号调用sys_zcycopyfile,就会通过系统调用产生一个int0x80的软中断,就会进入到系统调用的入口函数,找到这个调用函数表查找入口函数,也就是这里的.longsys_zcycopyfile,进而在sys.c中找到具体的函数实现asmlinkageintsys_zcycopychar*s_file,constchar*t_file),从而实现系统调用。

(5)配置内核:

(先cd到下载的新的内核包)

①净化解压后的源代码

makemrproper

②安装ncurses环境:

apt-getinstalllibncurses5-dev

ncurses是一个能提供基于文本终端窗口功能的动态库,提供字符终端处理库,包括面板和菜单。

③对内核选项进行配置

makemenuconfig

执行命令之后,会弹出一个框,提示对内核裁剪或配置。

这次用不到变化内核模块,直接用键盘方向键选项就行了。

④建立模块间的依赖信息

makedep

这一步正常情况会提示用户多此一举

⑤删除配置时留下的一些不用的文件

makeclean

这一步一般没动作,除非是失败后再次编译内核时要用到。

(6)编译内核:

①编译内核文件bzImage:

makebzImage–j9

这一步耗费的时间比较长,所以加了一个-j9,这种方法使用多线程编程,实际使用时发现能很大的提高效率。

(这个视CPU而定,要看CPU最多支持几个线程)

②编译内核模块:

makemodules–j9

(7)安装内核

经过最麻烦的编译内核,接下来的安装内核就显得容易多了,输入命令

sudomakemodules_install安装内核模块

sudomakeinstall安装内核

同样,如果嫌时间太慢的话,同样可以在最后加上–j9

(8)环境修改:

接下来主要是将编译安装生成的操作系统让系统引导程序“知道”,具体过程如下图4-4所示:

图4-4环境修改

具体如下:

①复制内核到boot目录:

cparch/i386/boot/bzImage/boot/vmlinuz-3.0.69.zcy

可利用Tab快速补全路径和文件,这样方便又不容易出错。

②建立要载入ramdisk的映像文件

mkinitramfs3.0.69.zcy-o/boot/initrd.img-3.0.69-zcy

③更新启动项文件grub2.conf,直接输入命令update-grub2就行。

(9)最后需要修改/boot/grub/目录下grub.cfg文件;

进入文件之后,按Ctrl+F查找timeout,将所有的timeout数值改为100;这个数值的单位是秒,这么做的目的是修改启动项的暂停时间,以便让用户有足够的时间选择要进入的操作系统。

 

(10)重启,进入新系统:

启动项如下图4-5所示:

图4-5系统启动项

※原版本内核比新内核小,入口在PreviousLinuxversion目录下,如下图4-6所示:

以上做的工作相当于在添加新的系统调用的同时还更新了系统。

图4-6旧的系统入口显示

(11)进入新系统之后,输入命令uname–a/-r查看系统新版本:

执行情况如下图4-7所示。

可知已经成功的进入到修改后的新内核3.0.69.zcy

图4-7显示新内核信息

 

(12)编写测试程序zcopy.c,如下图4-8所示:

图4-8测试程序,检测新的第347号系统调用

(13)编译运行,生成执行文件。

然后看执行程序是否可以实现文件的拷贝,执行结果如下图4-9和图4-10所示,可看到已经成功的实现了预计的功能。

图4-9执行程序

图4-10程序执行显示结果

5.内容三:

掌握添加设备驱动程序的方法

5.1内容要求

(1)采用模块方法,添加一个新的设备驱动程序。

(2)要求添加字符设备的驱动。

(3)编写一个应用程序,测试添加的驱动程序

5.2设计过程及实现

(1)Linux内核中的设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程。

对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文件,用户程序可以象对其它文件一样对此设备文件进行操作。

Linux支持3种设备:

字符设备、块设备和网络设备。

设备由一个主设备号和一个次设备号标识。

主设备号唯一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。

次设备号仅由设备驱动程序解释,一般用于识别在若干可能的硬件设备中,I/O请求所涉及到的那个设备。

一个典型的驱动程序,大体上可以分为这么几个部分:

①注册设备:

在系统初启,或者模块加载时候,必须将设备登记到相应的设备数组,并返回设备的主设备号;

②定义功能函数:

对于每一个驱动函数来说,都有一些和此设备密切相关的功能函数。

以最常用的块设备或者字符设备来说,都存在着诸如open()、read()这一类的操作。

当系统调用这些调用时,将自动的使用驱动函数中特定的模块。

来实现具体的操作;

③卸载设备:

在不用这个设备时,可以将它卸载,主要是从/proc中取消这个设备的特殊文件。

 

(2)编写Makefile文件如下:

ifneq($(KERNELRELEASE),)

obj-m:

=zcydriver.o//obj-m表示编译连接后将生成zcydriver.o模块

else

PWD:

=$(shellpwd)//PWD为当前目录

KVER:

=$(shelluname-r)//KVER为当前系统内核版本

KDIR:

=/lib/modules/$(KVER)/build

all:

$(MAKE)-C$(KDIR)M=$(PWD)//调用内核模块编译

clean:

#rm-f*.cmd*.o*.mod*.ko

rm-rf.*.cmd*.o*.mod.c*.ko.tmp_versions

#$(MAKE)-C$(KDIR)M=$(PWD)clean

endif

调用Makefile文件之后,其具体过程如下:

①KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容;

②如果make的目标是clean,直接执行clean操作,然后结束。

③当make的目标为all时,-C$(KDIR)指明跳转到内核源码目录下读取那里的Make$(PWD)表明然后返回到当前目录继续读入、执行当前的Makefile。

④当从内核源码目录返回时,KERNELRELEASE已被定义,内核的build程序Kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。

⑤else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名。

(3)编写设备功能函数:

(zcydriver.c)

函数框架如下所示:

#defineMY_M

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

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2