计算机操作系统-课设-操作系统.docx_第1页
计算机操作系统-课设-操作系统.docx_第2页
计算机操作系统-课设-操作系统.docx_第3页
计算机操作系统-课设-操作系统.docx_第4页
计算机操作系统-课设-操作系统.docx_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

课 程 设计 报 告课程名称: 操作系统原理_ 专业班级: _ 学 号: _ 姓 名: _ 指导教师: _ 报告日期: 2016年3月15日 计算机科学与技术学院目录1 课程设计目的12 课程设计环境搭建13 内容一:熟悉和理解Linux编程环境23.1 内容要求23.2 设计过程及实现24.内容二:掌握添加系统调用的方法94.1 内容要求94.2 设计过程及实现95.内容三:掌握添加设备驱动程序的方法175.1 内容要求175.2 设计过程及实现17241 课程设计目的(1)掌握Linux操作系统的使用方法;(2)了解Linux系统内核代码结构;(3)掌握实例操作系统的实现方法。2 课程设计环境搭建(1)安装linux系统:Ubuntu 14.04 内核:3.19.0-51-generic(2)在添加系统调用中用到的其他内核包:在相关的网站下载合适的linux内核下载结果是linux-3.18.27.tar.xz解压命令:tar xjvf linux-3.18.27.tar.xz C /usr/src解压后,在/usr/src目录下得到内核文件夹linux-3.18.27(3)在调用linux图形库时需要安装GTK环境:安装gcc/g+/gdb/make 等基本编程工具apt-get install build-essential 安装 libgtk2.0-dev libglib2.0-dev 等开发相关的库文件:apt-get install gnome-core-devel 安装GTK核心组件: apt-get install libgtk2.0-dev3 内容一:熟悉和理解Linux编程环境3.1 内容要求(1)编写一个C程序,实现文件拷贝功能(2)编写一个C程序,使用Linux下的图形库,分窗口显示三个并发进程运行;3.2 设计过程及实现(1)文件拷贝: 文件的拷贝主要的思想就是利用文件指针操作,在两个文件之间进行按字符的fget和fput。从而完成整个文件的拷贝操作。在这个基本功能之外,需要增加程序的健壮性,具体有以下几个方面:源文件是否存在且能读取数据;是否能创建目的文件,且能向里面写入数据;程序需要的argc参数个数是否满足要求; 主要的程序段如下:if(argc!=3) /判断参数个数是否为3 ,否则返回printf(Error in argc!);exit(1);/打开源文件if(from_fd=open(argv1,O_RDONLY)=-1)/文件描述符printf(Error in open source file!);exit(1);/创建目的文件if(to_fd=open(argv2,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)=-1)/权限printf(Error in open target file);exit(1); /拷贝文件while(bytes_read=read(from_fd,buffer,BUFFER_SIZE)/返回所读取的字节数if(bytes_read=-1)&(errno!=EINTR) break;/读过程遇到中断else if(bytes_read0)ptr=buffer; while(bytes_write=write(to_fd,ptr,bytes_read) if(bytes_write=-1)&(errno!=EINTR)break; else if(bytes_write=bytes_read) break; else if(bytes_write0) ptr+=bytes_write; bytes_read-=bytes_write;/ptr指向尚未写入的剩余数据首地址,bytes_read重新赋值为剩余数据大小,继续写.如此循环直到读到的数据全部写入为止.if(bytes_write=-1)break;/退出read循环 执行结果如下:将source.txt文件拷贝到到target.txt,开始时如下图3-1所示:图3-1 复制开始前source.txt文件内容利用copy程序复制,查看target.txt文件复制结果如下图3-2所示:图3-2 复制后target.txt文件的具体内容(2)实现三个进程之间的并发程序:这里需要用到课程实验时的fork( )程序以及GTK的图形显示。 基本fork()程序,调用显示一个父进程和两个子进程的结构如下: if(pid_1=fork()=0) printf(子进程1运行.n); /第一个子进程 show(argc,argv,子进程 1); /调用函数显示窗口 else if(pid_2=fork()=0) printf(子进程2运行.n); show(argc,argv,子进程2); else printf(父进程运行.n); /父进程调用GTK显示窗体函数模块的结构:void show(int argc,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 ,ID:%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_swapped (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 (); 编译代码fork.c,运行;编译命令为:gcc -o fork fork.c pkg-config -cflags -libs gtk+-2.0程序运行结果如下图3-3所示:图3-3 三个并行显示窗口4.内容二:掌握添加系统调用的方法4.1 内容要求(1)采用编译内核的方法,添加一个新的系统调用。(2)编写一个应用程序,测试新添加的系统调用。(3)系统调用的功能:文件拷贝。4.2 设计过程及实现(1)修改Makefile文件,修改系统版本后缀:如下图4-1所示:这里加的是本人的姓名的首字母,以示区分。图4-1 修改Makefile文件版本(2)修改/usr/src/ linux-3.18.27/kernel/目录下的sys.c文件,在最后加入新的系统调用,拷贝函数实现。如下所示:asmlinkage int sys_yzdcopyfile(const char* s_file, const char* t_file) const int BUF_SIZE = 512; int fin,fout; char bufBUF_SIZE; int copy_count; mm_segment_t fs; /段操作的初始化 fs = get_fs(); set_fs(get_ds();/* 系统调用打开源文件,若失败,返回-1 */ if (fin = sys_open(s_file,O_RDONLY,S_IRUSR) = -1) return -1; printk(Error in open source file!); /* 系统调用创建并打开目标文件,若失败,返回-2 */ if (fout = sys_open(t_file,O_RDWR | O_CREAT | O_TRUNC,S_IRUSR | S_IWUSR) = -1) return -2; printk(Error in open target file!); while(copy_count=sys_read(fin,buf,BUF_SIZE) /* 拷贝文件,若失败,返回-3 */ if (copy_count = -1 | sys_write(fout,buf,copy_count) = -1) return -3; printk(Error in copy file!); set_fs(fs); return 0; (3)添加系统调用号,修改文件 /arch/x86/systemcalls/syscall_64.tbl具体截图如下图4-2所示。图4-2 添加系统调用号(4)添加声明到头文件,修改文件,/include/linux/syscalls.h具体实现如下图4-3所示:图4-3 填写系统调用入口表 当用户程序需要系统提供服务的时候,比如调用sys_yzdcopyfile,就会通过系统调用产生一个int 0x80的软中断,就会进入到系统调用的入口函数,找到这个调用函数表查找入口函数,进而在sys.c中找到具体的函数实现asmlinkage int sys_yzdcopyfile(const char* s_file, const char* t_file) ,从而实现系统调用。(5)配置内核:(先cd到下载的新的内核包)净化解压后的源代码make mrproper安装ncurses环境: apt-get install libncurses5-devncurses是一个能提供基于文本终端窗口功能的动态库, 提供字符终端处理库,包括面板和菜单。对内核选项进行配置make menuconfig执行命令之后,会弹出一个框,提示对内核裁剪或配置。这次用不到变化内核模块,直接用键盘方向键选项就行了。建立模块间的依赖信息make dep这一步正常情况会提示用户多此一举删除配置时留下的一些不用的文件make clean这一步一般没动作,除非是失败后再次编译内核时要用到。(6)编译内核:编译内核文件bzImage:make bzImage 这一步耗费的时间比较长编译内核模块:make modules (7)安装内核输入命令sudo make modules_install 安装内核模块sudo make install 安装内核(8)环境修改:直接修改/etc/default/grub(然后update-grub) 进入文件之后,将所有的timeout数值改为10;这个数值的单位是秒,这么做的目的是修改启动项的暂停时间,以便让用户有足够的时间选择要进入的操作系统。(9)重启,进入新系统(10)进入新系统之后,输入命令uname -r查看系统新版本:执行情况如下图4-4所示。可知已经成功的进入到修改后的新内核图4-4 显示新内核信息(11)编写测试程序copy2.c,如下所示:图4-5 测试程序(12)编译运行,生成执行文件。然后看执行程序是否可以实现文件的拷贝,执行结果如下图4-6和图4-7所示,可看到已经成功的实现了预计的功能。图4-6 执行程序图4-7 程序执行结果5.内容三:掌握添加设备驱动程序的方法5.1 内容要求(1)采用模块方法,添加一个新的设备驱动程序。(2)要求添加字符设备的驱动。(3)编写一个应用程序,测试添加的驱动程序5.2 设计过程及实现 (1)Linux内核中的设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程。对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文件,用户程序可以象对其它文件一样对此设备文件进行操作。 Linux支持3种设备:字符设备、块设备和网络设备。设备由一个主设备号和一个次设备号标识。主设备号唯一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,一般用于识别在若干可能的硬件设备中,I/O请求所涉及到的那个设备。 一个典型的驱动程序,大体上可以分为这么几个部分: 注册设备:在系统初启,或者模块加载时候,必须将设备登记到相应的设备数组,并返回设备的主设备号; 定义功能函数:对于每一个驱动函数来说,都有一些和此设备密切相关的功能函数。以最常用的块设备或者字符设备来说,都存在着诸如 open()、read()这一类的操作。当系统调用这些调用时,将自动的使用驱动函数中特定的模块。来实现具体的操作;卸载设备:在不用这个设备时,可以将它卸载,主要是从/proc 中取消这个设备的特殊文件。 (2)编写Makefile文件如下:obj-m += testdriver.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean(3)编写设备功能函数:(testdriver.c)函数框架如下所示:#define MY_MAJOR 240/定义设备号int testdriver_open(struct inode *inode, struct file *filp) /打开设备 printk(.testdriver_openn); return 0;ssize_t testdriver_read(struct file *filp, char _user *buf, size_t count, loff_t *f_pos)sprintf(s2,%s,s1);if(count12) if(!copy_to_user(buf,s2,count)return 0;elseif(!copy_to_user(buf,s2,strlen(s2)return 0;return -1;ssize_t testdriver_write(struct file *filp, char _user *buf, size_t count, loff_t *f_pos) if (count 0) return -EINVAL;/无效参数 if (s1 = NULL) return -ENOMEM;/内存不足 if (copy_from_user(s1, buf, count+1) return -EFAULT;/指向无效地址 return count;int testdriver_release(struct inode *inode, struct file *filp) printk(testdriver_releasen); return 0;struct file_operations testdriv

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论